A simple form validation library written in Swift 4.2.
Features
-
Built-in validators
- Mandatory
- Maxlength (currently only
UITextFieldare supported) is a special one. Use storyboard to set it up. - Minlength
- DigitsOnly
- EqualTo (an input value equals to another inputs value)
- AlphaNumeric
- Regular expressions
-
Custom validators
-
Validates any
UITextFieldorUITextViewor you can create your own validatable input fields -
Add custom styles to highlight invalid input fields
-
Conditional validation
Demo
Requirements
- iOS 8.0+
- Xcode 8.2+
- Swift 3.0+
Installation
The recommended approach to use EGFormValidator in your project is using the CocoaPods package manager, as it provides flexible dependency management and dead simple installation.
CocoaPods
Install CocoaPods if not already available:
$ [sudo] gem install cocoapods $ pod setup
Go to the directory of your Xcode project, and Create and Edit your Podfile and add EGFormValidator to your corresponding TargetName:
$ cd /path/to/MyProject $ touch Podfile $ edit Podfile source 'https://github.com/CocoaPods/Specs.git' platform :ios, '9.0' use_frameworks! target 'TargetName' do pod 'EGFormValidator' end
Install into your project:
Open your project in Xcode from the .xcworkspace file (not the usual project file):
$ open MyProject.xcworkspace
You can now import EGFormValidator framework into your files.
Usage
Basic
1. Extend ValidatorViewController
class MyViewController: ValidatorViewController { }
2. Place your validators in viewDidLoad in the order that they has to be executed.
override func viewDidLoad() { super.viewDidLoad() // // Place your validation code here // // Mandatory validation self.addValidatorMandatory(toControl: self.fullnameTextfield, errorPlaceholder: self.fullnameErrorLabel, errorMessage: "This field is required") // Minlength self.addValidatorMinLength(toControl: self.fullnameTextfield, errorPlaceholder: self.fullnameErrorLabel, errorMessage: "Enter at least %d characters", minLength: 8) // Email self.addValidatorEmail(toControl: self.emailTextField, errorPlaceholder: self.emailErrorLabel, errorMessage: "Email is invalid") // Digits Only self.addValidatorDigitsOnly(toControl: self.postalCodeTextfield, errorPlaceholder: self.postalCodeErrorLabel, errorMessage: "Postal code must contain only digits") // Equalty self.addValidatorEqualTo(toControl: self.passwordConfirmationTextField, errorPlaceholder: self.passwordConfirmationErrorLabel, errorMessage: "Passwords don't match", compareWithControl: self.passwordTextField) // AlphaNumeric self.addValidatorAlphaNumeric(toControl: self.alphaNumericTextField, errorPlaceholder: self.aphaNumericErrorLabel, errorMessage: "Only letters and digits are allowed") }
3. Execute self.validate() to validate your form
if self.validate() { // form is valid }
Add styles: highlight valid and invalid inputs
Just implement setValidation optional method of Validatable protocol . For example:
import UIKit class SuperTextField: UITextField, Validatable { // textfield initializatin override init(frame: CGRect) { super.init(frame: frame) xibSetup() } required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) xibSetup() } func xibSetup() { layer.cornerRadius = 6 layer.borderWidth = 2 setNormalBorderColor() } func setNormalBorderColor() { layer.borderColor = UIColor(red: 244.0/255.0, green: 177.0/255.0, blue: 61.0/255.0, alpha: 1.0).cgColor textColor = UIColor(red: 86.0/255.0, green: 86.0/255.0, blue: 86.0/255.0, alpha: 1.0) backgroundColor = .white } // // MARK: - Validatable protocol implementation func setValidation(state: ValidatableControlState) { if state == .error { layer.borderColor = UIColor(red: 230.0/255.0, green: 47.0/255.0, blue: 44.0/255.0, alpha: 1.0).cgColor textColor = .white backgroundColor = UIColor(red: 239.0/255.0, green: 158.0/255.0, blue: 158.0/255.0, alpha: 1.0) } else { setNormalBorderColor() } } }
Custom validators
Create a validator:
let myNewShinyValidator = Validator(control: control, // any class that conforms Validatable protocol: use UITextField, UITextView or create your own (for more, see 'Custom input fields' section) predicate: AlphaNumericValidatorFunction // a function that complies (Any?, [Any?]) -> Bool predicateParameters: [], // Pass as many extra parametes as you want errorPlaceholder: errorPlaceholderLabel, // anything that conforms ValidationErrorDisplayable protocol: use UILabel or create your own (for more, see 'Custom error placeholders' section) errorMessage: "This input is invalid") // Error message
Create a predicate:
func AlphaNumericValidatorFunction(value: Any?, params: [Any?]) -> Bool { let badCharacters = NSCharacterSet.alphanumerics.inverted if let myString = value as? String, myString.rangeOfCharacter(from: badCharacters) == nil { return true } return false }
Use self.add(validator: myNewShinyValidator) to add your validator.
Custom input fields
Just implement Validatable protocol's required getValue method. For example:
import UIKit extension MyDropDown: Validatable { // MARK - Validatable Protocol Implementation func getValue() -> Any? { return self.text // it must return a value that will be validated } }
Custom error placeholders
Implement ValidationErrorDisplayable protocol's required setErrorMessage method. For example:
import UIKit extension SomeCustomView: ValidationErrorDisplayable { // MARK - Validation Error Displayable protocol implementation func setErrorMessage(errorMessage: String?) { // do stuff to show an error message self.errorLabel.text = errorMessage } }
Conditional validation
You can define wheather you want to apply a specific validator or not. Simply add a condition to a validator.
For a custom validator:
self.add(validator: aValidator, condition: { () -> Bool { return false // return true if you want to apply this validator and false otherwise })
For a core validator:
// in this case it's digit-only validator, the same syntax is applied to the others self.addValidatorDigitsOnly(toControl: self.myTextfield, errorPlaceholder: self.myTextfieldErrorLabel, errorMessage: "Digits only please") { () -> Bool { return false // return true if you want to apply this validator and false otherwise }
Let's say if you have two fields: a landline and a cellphone. And you want a user to fill in at least one of them.
self.addValidatorMandatory(toControl: self.cellphoneTextfield, errorPlaceholder: self.cellphoneErrorLabel, errorMessage: "Please enter your home phone number or your cellphone") { [unowned self] () -> Bool in if let landline = self.landlineTextfield.getValue() as? String, landline.characters.count > 0 { return false } return true } self.addValidatorMandatory(toControl: self.landlineTextfield, errorPlaceholder: self.landlineErrorLabel, errorMessage: "Please enter your home phone number or your cellphone") { [unowned self] () -> Bool in if let cellphone = self.cellphoneTextfield.getValue() as? String, cellphone.characters.count > 0 { return false } return true }