以前 Validatorというライブラリを使ってValidationするという記事で、Validatorの基本的な使い方を紹介しました。
実際のアプリケーションに適用する場合、単一のValidationルールでは足りないことがあります。
Validator自体はValidationRuleSet
という構造体で複数のルールを保持できるようになっていますが、都度都度ValidationRuleSet
にルールを追加していくのも面倒ですし、同じ項目が複数箇所に出てきた際にロジックが分散するとちょっとイヤです。
ユーザIDならユーザID用の精査ルールを持ちたいので、独自のルールを作成することにします。
以下に記載されている通り、ValidationRule
プロトコルを適用した構造体を作成すれば良いです。
独自のルールを作成する
独自のルールを作成するといっても、往々にして既存のルールの組み合わせなことがほとんどだと思います。
以下では、ユーザID用のルールをValidationRuleLength
とValidationRulePattern
の組み合わせで作成しました。
ルールとしては、
- 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: "💩")))
実際もっとスマートな方法があるような気もするのですが、これでロジックの分散が防げ、この項目の精査はコレ、と迷わず選択できるようになると思います。