Validation logic disappears when implemented using various UITextFieldDelegate
methods. It generally becomes extremely hard to fulfil complicated requirements, and when you do, it becomes really hard to understand/reuse/maintain later on. GKValidator
makes this process easier.
ValidationRule
|
FieldValidator
|
FieldValidationDelegate
|
FormValidator
ValidationRule<Type>
or GenericValidationRule
encapsulates a rule to be used for validation. Defining rules is as simple as following:
// Define a rule to check if (string.length > 10).
let lengthRule = ValidationRule<String> { (value) -> Bool in
return value?.characters.count > 10
}
// Define an error object to be returned upon failure. (Optional)
let matchPasswordsError = ValidationError(code: 1000, localizedDescription: "Passwords do not match.")
// Define a generic rule to check if password fields' text match.
let matchPasswordsRule = GenericValidationRule(error: matchPasswordsError) { () -> Bool in
return passwordField.text == rePasswordField.text
}
FieldValidator
keeps all rules to validate a field during its lifecycle.
You should validate user input before accepting it. Use inputRuleSet
to store your rules for this purpose.
You should apply 3 type of validations to determine field's state.
Completeness
: Validate to see if field is complete, so that we can proceed to next field.Eligibility
: Validate to see if field's value is valid, so that we can enable submit button.Submission
: Validate to see if field's value matches with our criteria (for server, database, etc.) after submit button is tapped.
If requirements are as follows:
- Should not accept more than 12 characters.
- Should only accept digits.
- Should proceed to next field if it has 12 characters already.
- Should not be eligible to submit if it has less than 8 characters.
- Should not be submittable if it does not start with digit 9. (Alert: "Number should start with 9.")
Your validator would be:
let validator = TextFieldValidator()
// Add input rules
validator.addInputRules([
TextValidationRule(maxLength: 12),
TextValidationRule(characterSet: NSCharacterSet.decimalDigitCharacterSet())
])
// Add completeness rules
validator.addValidationRules([TextValidationRule(minLength: 12)], forType: .Completeness)
// Add eligibility rules
validator.addValidationRules([TextValidationRule(minLength: 8)], forType: .Eligibility)
// Add submission rules
let firstDigitError = ValidationError(code: 1002, localizedDescription: "Number should start with 9.")
let firstDigitRule = TextValidationRule(error: firstDigitError) { (value) -> Bool in
if let digit = Int(String(value?.characters.first)) {
return digit == 9
}
else {
return false
}
}
validator.addValidationRules([firstDigitRule], forType: .Submission)
FieldValidationDelegate
expects a field of type ValidatableField
and a validator. It simply takes care of validation.
FieldValidationDelegate<String>(field: emailField, validator: emailValidator)
FormValidator
encapsulates logic for field-validation and general form-validation.
- Observes
FieldValidationDelegate
objects to determine overall form state. This way you can easily see if your form is ready for submission or not. - Defines general validation rules for form. (Like:
passwordField.text == rePasswordField.text
)
It's recommended to create a subclass of
FormValidator
for each form you have.
Your subclass' init method should look like this:
// Create field delegates.
...
// Pass field delegates for observation.
self.fieldValidationDelegates = [
displayNameFieldDelegate,
usernameFieldDelegate,
emailFieldDelegate,
passwordFieldDelegate,
rePasswordFieldDelegate,
mobileNumberFieldDelegate,
]
// Add generic form validation rules.
let matchPasswordsError = ValidationError(code: 1000, localizedDescription: "Passwords do not match.")
let matchPasswordsRule = GenericValidationRule(error: matchPasswordsError) { () -> Bool in
return passwordField.text == rePasswordField.text
}
let tAndCError = ValidationError(code: 1001, localizedDescription: "Please accept terms and conditions.")
let tAndCRule = GenericValidationRule(error: tAndCError) { () -> Bool in
return tAndCSwitch.on
}
self.addValidationRules([
matchPasswordsRule,
tAndCRule,
], forType: .Submission)
Please see Example project for more details.
To run the example project, clone the repo, and run pod install
from the Example directory first.
GKValidator is available through CocoaPods. To install it, simply add the following line to your Podfile:
pod 'GKValidator', '~> 2.0'
- Swift 2.2: Use version
0.X.X
- Swift 3: Use version
1.X.X
- Swift 4: Use version
2.X.X
Göksel Köksal, [email protected]
GKValidator is available under the MIT license. See the LICENSE file for more info.