LoginSignup
5
7

More than 5 years have passed since last update.

[Swift] Validatorで独自のValidationRuleを作成する

Posted at

以前 Validatorというライブラリを使ってValidationするという記事で、Validatorの基本的な使い方を紹介しました。

実際のアプリケーションに適用する場合、単一のValidationルールでは足りないことがあります。
Validator自体はValidationRuleSetという構造体で複数のルールを保持できるようになっていますが、都度都度ValidationRuleSetにルールを追加していくのも面倒ですし、同じ項目が複数箇所に出てきた際にロジックが分散するとちょっとイヤです。

ユーザIDならユーザID用の精査ルールを持ちたいので、独自のルールを作成することにします。
以下に記載されている通り、ValidationRuleプロトコルを適用した構造体を作成すれば良いです。

独自のルールを作成する

独自のルールを作成するといっても、往々にして既存のルールの組み合わせなことがほとんどだと思います。
以下では、ユーザID用のルールをValidationRuleLengthValidationRulePatternの組み合わせで作成しました。

ルールとしては、

  • 0桁以上16桁以下
  • 英数字

と適当にしています。

英数字を表すパターンも独自に作成します。
こちらはValidationPatternプロトコルを適用したenumです。
英数字以外にも英字、数字のみのパターンも用意してみました。

import Foundation
import Validator

public enum CharacterTypeValidationPattern: ValidationPattern {
    case alpha
    case alphaNumeric
    case numeric
    public var pattern: String {
        switch self {
        case .alpha: return "^[A-Za-z]+$"
        case .alphaNumeric :return "^[A-Za-z0-9]+$"
        case .numeric :return "^[0-9]+$"
        }
    }
}

作成したルールは以下です。
複数ルールを作成し、validateで両方のルールに適していればtrue、片方でもValidationエラーの場合はfalseが返るようにしています。

import Foundation
import Validator

/**
 Validation rule for userId.
 */
public struct ValidationRuleUserId: ValidationRule {
    public typealias InputType = String
    public var error: Error
    public let lengthRule: ValidationRuleLength
    public let patternRule: ValidationRulePattern
    public init(error: Error) {
        self.error = error
        self.lengthRule = ValidationRuleLength(min: 0, max: 16, error: self.error)
        self.patternRule =
            ValidationRulePattern(pattern: CharacterTypeValidationPattern.alphaNumeric, error: self.error)
    }
    /**

     Validates the input.

     - Parameters:
     - input: Input to validate.

     - Returns:
     true: valid, false: inValid

     */
    public func validate(input: String?) -> Bool {
        return self.lengthRule.validate(input: input) && self.patternRule.validate(input: input)
    }
}

使い方はこんな感じで、通常のルールと同様です。

@IBOutlet weak var userIdInput: UITextField!
let userIdValidateResult = userIdInput.validate(rule: ValidationRuleUserId(error: ValidationError(message: "💩")))

実際もっとスマートな方法があるような気もするのですが、これでロジックの分散が防げ、この項目の精査はコレ、と迷わず選択できるようになると思います。

5
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
7