Removed UITextField limitations and switched to Validatable protocol

This commit is contained in:
Deniz Adalar 2016-05-04 13:39:14 +03:00
parent 344b178af5
commit 8f116df330
21 changed files with 144 additions and 102 deletions

View File

@ -0,0 +1,25 @@
//
// Validatable.swift
// Validator
//
// Created by Deniz Adalar on 28/04/16.
// Copyright © 2016 jpotts18. All rights reserved.
//
import Foundation
public typealias ValidatableField = protocol<AnyObject, Validatable>
public protocol Validatable {
var validationText: String {
get
}
}
extension UITextField: Validatable {
public var validationText: String {
return text ?? ""
}
}

View File

@ -11,7 +11,7 @@ import UIKit
/**
Protocol for `ValidationDelegate` adherents, which comes with two required methods that are called depending on whether validation succeeded or failed.
*/
@objc public protocol ValidationDelegate {
public protocol ValidationDelegate {
/**
This method will be called on delegate object when validation is successful.
@ -23,5 +23,5 @@ import UIKit
- returns: No return value.
*/
func validationFailed(errors: [UITextField:ValidationError])
func validationFailed(errors: [(Validatable, ValidationError)])
}

View File

@ -7,38 +7,38 @@ import Foundation
import UIKit
/**
The `ValidationError` class is used for representing errors of a failed validation. It contains the text field, error label, and error message of a failed validation.
The `ValidationError` class is used for representing errors of a failed validation. It contains the field, error label, and error message of a failed validation.
*/
public class ValidationError: NSObject {
/// the textField of the field
public let textField:UITextField
/// the Validatable field of the field
public let field:ValidatableField
/// the error label of the field
public var errorLabel:UILabel?
/// the error message of the field
public let errorMessage:String
/**
Initializes `ValidationError` object with a textField and error.
Initializes `ValidationError` object with a field and error.
- parameter textField: UITextField that holds textField.
- parameter field: Validatable field that holds field.
- parameter errorMessage: String that holds error message.
- returns: An initialized object, or nil if an object could not be created for some reason that would not result in an exception.
*/
public init(textField:UITextField, error:String){
self.textField = textField
public init(field:ValidatableField, error:String){
self.field = field
self.errorMessage = error
}
/**
Initializes `ValidationError` object with a textField, errorLabel, and errorMessage.
Initializes `ValidationError` object with a field, errorLabel, and errorMessage.
- parameter textField: UITextField that holds textField.
- parameter field: Validatable field that holds field.
- parameter errorLabel: UILabel that holds error label.
- parameter errorMessage: String that holds error message.
- returns: An initialized object, or nil if an object could not be created for some reason that would not result in an exception.
*/
public init(textField:UITextField, errorLabel:UILabel?, error:String){
self.textField = textField
public init(field:ValidatableField, errorLabel:UILabel?, error:String){
self.field = field
self.errorLabel = errorLabel
self.errorMessage = error
}

View File

@ -14,10 +14,12 @@ import UIKit
*/
public class Validator {
/// Dictionary to hold all fields (and accompanying rules) that will undergo validation.
public var validations = [UITextField:ValidationRule]()
public var validations = [ObjectIdentifier:ValidationRule]()
/// Dictionary to hold fields (and accompanying errors) that were unsuccessfully validated.
public var errors = [UITextField:ValidationError]()
/// Variable that holds success closure to display positive status of field.
public var errors = [ObjectIdentifier:ValidationError]()
/// Dictionary to hold fields by their object identifiers
private var fields = [ObjectIdentifier:Validatable]()
/// Variable that holds success closure to display positive status of field.
private var successStyleTransform:((validationRule:ValidationRule)->Void)?
/// Variable that holds error closure to display negative status of field.
private var errorStyleTransform:((validationError:ValidationError)->Void)?
@ -36,9 +38,9 @@ public class Validator {
errors = [:]
for (textField, rule) in validations {
for (field, rule) in validations {
if let error = rule.validateField() {
errors[textField] = error
errors[field] = error
// let the user transform the field if they want
if let transform = self.errorStyleTransform {
@ -60,13 +62,14 @@ public class Validator {
This method is used to validate a single field registered to Validator. If validation is unsuccessful,
field gets added to errors dictionary.
- parameter textField: Holds validator field data.
- parameter field: Holds validator field data.
- returns: No return value.
*/
public func validateField(textField: UITextField, callback: (error:ValidationError?) -> Void){
if let fieldRule = validations[textField] {
public func validateField(field: ValidatableField, callback: (error:ValidationError?) -> Void){
let oid = ObjectIdentifier(field)
if let fieldRule = validations[oid] {
if let error = fieldRule.validateField() {
errors[textField] = error
errors[oid] = error
if let transform = self.errorStyleTransform {
transform(validationError: error)
}
@ -99,35 +102,40 @@ public class Validator {
/**
This method is used to add a field to validator.
- parameter textField: field that is to be validated.
- parameter Rule: An array which holds different rules to validate against textField.
- parameter field: field that is to be validated.
- parameter Rule: An array which holds different rules to validate against field.
- returns: No return value
*/
public func registerField(textField:UITextField, rules:[Rule]) {
validations[textField] = ValidationRule(textField: textField, rules: rules, errorLabel: nil)
public func registerField(field:ValidatableField, rules:[Rule]) {
let oid = ObjectIdentifier(field)
validations[oid] = ValidationRule(field: field, rules: rules, errorLabel: nil)
fields[oid] = field
}
/**
This method is used to add a field to validator.
- parameter textfield: field that is to be validated.
- parameter field: field that is to be validated.
- parameter errorLabel: A UILabel that holds error label data
- parameter rules: A Rule array that holds different rules that apply to said textField.
- parameter rules: A Rule array that holds different rules that apply to said field.
- returns: No return value
*/
public func registerField(textField:UITextField, errorLabel:UILabel, rules:[Rule]) {
validations[textField] = ValidationRule(textField: textField, rules:rules, errorLabel:errorLabel)
public func registerField(field: ValidatableField, errorLabel:UILabel, rules:[Rule]) {
let oid = ObjectIdentifier(field)
validations[oid] = ValidationRule(field: field, rules:rules, errorLabel:errorLabel)
fields[oid] = field
}
/**
This method is for removing a field validator.
- parameter textField: field used to locate and remove textField from validator.
- parameter field: field used to locate and remove field from validator.
- returns: No return value
*/
public func unregisterField(textField:UITextField) {
validations.removeValueForKey(textField)
errors.removeValueForKey(textField)
public func unregisterField(field:ValidatableField) {
let oid = ObjectIdentifier(field)
validations.removeValueForKey(oid)
errors.removeValueForKey(oid)
}
/**
@ -142,7 +150,7 @@ public class Validator {
if errors.isEmpty {
delegate.validationSuccessful()
} else {
delegate.validationFailed(errors)
delegate.validationFailed(errors.map { (fields[$0]!, $1) })
}
}
@ -150,13 +158,13 @@ public class Validator {
/**
This method validates all fields in validator and sets any errors to errors parameter of callback.
- parameter callback: A closure which is called with errors, a dictionary of type UITextField:ValidationError.
- parameter callback: A closure which is called with errors, a dictionary of type Validatable:ValidationError.
- returns: No return value.
*/
public func validate(callback:(errors:[UITextField:ValidationError])->Void) -> Void {
public func validate(callback:(errors:[(Validatable, ValidationError)])->Void) -> Void {
self.validateAllFields()
callback(errors: errors)
callback(errors: errors.map { (fields[$0]!, $1) } )
}
}

View File

@ -45,7 +45,7 @@ public class CharacterSetRule: Rule {
}
/**
Displays error message when text field fails validation.
Displays error message when field fails validation.
- returns: String of error message.
*/

View File

@ -10,35 +10,35 @@ import Foundation
import UIKit
/**
`ConfirmationRule` is a subclass of Rule that defines how a text field that has to be equal
to another text field is validated.
`ConfirmationRule` is a subclass of Rule that defines how a field that has to be equal
to another field is validated.
*/
public class ConfirmationRule: Rule {
/// parameter confirmField: text field to which original text field will be compared to.
private let confirmField: UITextField
/// parameter confirmField: field to which original text field will be compared to.
private let confirmField: ValidatableField
/// parameter message: String of error message.
private var message : String
/**
Initializes a `ConfirmationRule` object to validate the text of a text field that should equal the text of another text field.
Initializes a `ConfirmationRule` object to validate the text of a field that should equal the text of another field.
- parameter confirmField: text field to which original text field will be compared to.
- parameter confirmField: field to which original field will be compared to.
- parameter message: String of error message.
- returns: An initialized object, or nil if an object could not be created for some reason that would not result in an exception.
*/
public init(confirmField: UITextField, message : String = "This field does not match"){
public init(confirmField: ValidatableField, message : String = "This field does not match"){
self.confirmField = confirmField
self.message = message
}
/**
Used to validate a text field.
Used to validate a field.
- parameter value: String to checked for validation.
- returns: A boolean value. True if validation is successful; False if validation fails.
*/
public func validate(value: String) -> Bool {
return confirmField.text == value
return confirmField.validationText == value
}
/**

View File

@ -16,7 +16,7 @@ public class EmailRule: RegexRule {
static let regex = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,6}"
/**
Initializes an `EmailRule` object to validate an email text field.
Initializes an `EmailRule` object to validate an email field.
- parameter message: String of error message.
- returns: An initialized object, or nil if an object could not be created for some reason that would not result in an exception.

View File

@ -9,7 +9,7 @@
import Foundation
/**
`ExactLengthRule` is a subclass of Rule that is used to make sure a the text of a text field is an exact length.
`ExactLengthRule` is a subclass of Rule that is used to make sure a the text of a field is an exact length.
*/
public class ExactLengthRule : Rule {
/// parameter message: String of error message.
@ -18,7 +18,7 @@ public class ExactLengthRule : Rule {
private var length : Int
/**
Initializes an `ExactLengthRule` object to validate the text of a text field against an exact length.
Initializes an `ExactLengthRule` object to validate the text of a field against an exact length.
- parameter length: Integer value of exact string length being specified.
- parameter message: String of error message.
@ -30,7 +30,7 @@ public class ExactLengthRule : Rule {
}
/**
Used to validate a text field.
Used to validate a field.
- parameter value: String to checked for validation.
- returns: A boolean value. True if validation is successful; False if validation fails.
@ -40,7 +40,7 @@ public class ExactLengthRule : Rule {
}
/**
Displays error message if a text field fails validation.
Displays error message if a field fails validation.
- returns: String of error message.
*/

View File

@ -16,7 +16,7 @@ public class FloatRule:Rule {
private var message : String
/**
Initializes a `FloatRule` object to validate that the text of a text field is a floating point number.
Initializes a `FloatRule` object to validate that the text of a field is a floating point number.
- parameter message: String of error message.
- returns: An initialized object, or nil if an object could not be created for some reason that would not result in an exception.
@ -26,7 +26,7 @@ public class FloatRule:Rule {
}
/**
Used to validate text field.
Used to validate field.
- parameter value: String to checked for validation.
- returns: Boolean value. True if validation is successful; False if validation fails.
@ -41,7 +41,7 @@ public class FloatRule:Rule {
}
/**
Displays error message when text field fails validation.
Displays error message when field fails validation.
- returns: String of error message.
*/

View File

@ -15,7 +15,7 @@ public class FullNameRule : Rule {
private var message : String
/**
Initializes a `FullNameRule` object that is used to verify that text in text field is a full name.
Initializes a `FullNameRule` object that is used to verify that text in field is a full name.
- parameter message: String of error message.
- returns: An initialized `FullNameRule` object, or nil if an object could not be created for some reason that would not result in an exception.
@ -25,7 +25,7 @@ public class FullNameRule : Rule {
}
/**
Used to validate a text field.
Used to validate a field.
- parameter value: String to checked for validation.
- returns: A boolean value. True if validation is successful; False if validation fails.
@ -36,7 +36,7 @@ public class FullNameRule : Rule {
}
/**
Used to display error message of a text field that has failed validation.
Used to display error message of a field that has failed validation.
- returns: String of error message.
*/

View File

@ -27,7 +27,7 @@ public class ISBNRule: Rule {
}
/**
Method used to validate text field.
Method used to validate field.
- parameter value: String to checked for validation.
- returns: Boolean value. True if validation is successful; False if validation fails.
@ -44,7 +44,7 @@ public class ISBNRule: Rule {
}
/**
Method used to dispaly error message when text field fails validation.
Method used to dispaly error message when field fails validation.
- returns: String of error message.
*/

View File

@ -19,7 +19,7 @@ public class MaxLengthRule: Rule {
public init(){}
/**
Initializes a `MaxLengthRule` object that is to validate the length of the text of a text field.
Initializes a `MaxLengthRule` object that is to validate the length of the text of a field.
- parameter length: Maximum character length.
- parameter message: String of error message.
@ -31,7 +31,7 @@ public class MaxLengthRule: Rule {
}
/**
Used to validate a text field.
Used to validate a field.
- parameter value: String to checked for validation.
- returns: A boolean value. True if validation is successful; False if validation fails.
@ -41,7 +41,7 @@ public class MaxLengthRule: Rule {
}
/**
Displays an error message if a text field fails validation.
Displays an error message if a field fails validation.
- returns: String of error message.
*/

View File

@ -21,7 +21,7 @@ public class MinLengthRule: Rule {
public init(){}
/**
Initializes a `MaxLengthRule` object that is to validate the length of the text of a text field.
Initializes a `MaxLengthRule` object that is to validate the length of the text of a field.
- parameter length: Minimum character length.
- parameter message: String of error message.
@ -33,7 +33,7 @@ public class MinLengthRule: Rule {
}
/**
Validates a text field.
Validates a field.
- parameter value: String to checked for validation.
- returns: A boolean value. True if validation is successful; False if validation fails.
*/
@ -42,7 +42,7 @@ public class MinLengthRule: Rule {
}
/**
Displays error message when text field has failed validation.
Displays error message when field has failed validation.
- returns: String of error message.
*/

View File

@ -24,7 +24,7 @@ public class PasswordRule : RegexRule {
static let regex = "^(?=.*?[A-Z]).{8,}$"
/**
Initializes a `PasswordRule` object that will validate a text field is a valid password.
Initializes a `PasswordRule` object that will validate a field is a valid password.
- parameter message: String of error message.
- returns: An initialized `PasswordRule` object, or nil if an object could not be created for some reason that would not result in an exception.

View File

@ -30,7 +30,7 @@ public class RegexRule : Rule {
}
/**
Method used to validate text field.
Method used to validate field.
- parameter value: String to checked for validation.
- returns: Boolean value. True if validation is successful; False if validation fails.
@ -41,7 +41,7 @@ public class RegexRule : Rule {
}
/**
Method used to dispaly error message when text field fails validation.
Method used to dispaly error message when field fails validation.
- returns: String of error message.
*/

View File

@ -9,7 +9,7 @@
import Foundation
/**
`RequiredRule` is a subclass of Rule that defines how a required text field is validated.
`RequiredRule` is a subclass of Rule that defines how a required field is validated.
*/
public class RequiredRule: Rule {
/// String that holds error message.
@ -26,7 +26,7 @@ public class RequiredRule: Rule {
}
/**
Validates a text field.
Validates a field.
- parameter value: String to checked for validation.
- returns: Boolean value. True if validation is successful; False if validation fails.

View File

@ -12,14 +12,14 @@ import Foundation
*/
public protocol Rule {
/**
Validates text of a text field.
Validates text of a field.
- parameter value: String of text to be validated.
- returns: Boolean value. True if validation is successful; False if validation fails.
*/
func validate(value: String) -> Bool
/**
Displays error message of a text field that has failed validation.
Displays error message of a field that has failed validation.
- returns: String of error message.
*/

View File

@ -9,36 +9,37 @@ import Foundation
import UIKit
/**
`ValidationRule` is a class that creates an object which holds validation info of a text field.
`ValidationRule` is a class that creates an object which holds validation info of a field.
*/
public class ValidationRule {
/// the text field of the field
public var textField:UITextField
/// the field of the field
public var field:ValidatableField
/// the errorLabel of the field
public var errorLabel:UILabel?
/// the rules of the field
public var rules:[Rule] = []
/**
Initializes `ValidationRule` instance with text field, rules, and errorLabel.
Initializes `ValidationRule` instance with field, rules, and errorLabel.
- parameter textField: text field that holds actual text in text field.
- parameter errorLabel: label that holds error label of text field.
- parameter rules: array of Rule objects, which text field will be validated against.
- parameter field: field that holds actual text in field.
- parameter errorLabel: label that holds error label of field.
- parameter rules: array of Rule objects, which field will be validated against.
- returns: An initialized `ValidationRule` object, or nil if an object could not be created for some reason that would not result in an exception.
*/
public init(textField: UITextField, rules:[Rule], errorLabel:UILabel?){
self.textField = textField
public init(field: ValidatableField, rules:[Rule], errorLabel:UILabel?){
self.field = field
self.errorLabel = errorLabel
self.rules = rules
}
/**
Used to validate text field against its validation rules.
Used to validate field against its validation rules.
- returns: `ValidationError` object if at least one error is found. Nil is returned if there are no validation errors.
*/
public func validateField() -> ValidationError? {
return rules.filter{ !$0.validate(self.textField.text ?? "") }
.map{ rule -> ValidationError in return ValidationError(textField: self.textField, errorLabel:self.errorLabel, error: rule.errorMessage()) }.first
return rules.filter{
return !$0.validate(field.validationText ?? "")
}.map{ rule -> ValidationError in return ValidationError(field: self.field, errorLabel:self.errorLabel, error: rule.errorMessage()) }.first
}
}

View File

@ -323,13 +323,13 @@ class SwiftValidatorTests: XCTestCase {
func testRegisterField(){
REGISTER_VALIDATOR.registerField(REGISTER_TXT_FIELD, rules: REGISTER_RULES)
XCTAssert(REGISTER_VALIDATOR.validations[REGISTER_TXT_FIELD] != nil, "Textfield should register")
XCTAssert(REGISTER_VALIDATOR.validations[ObjectIdentifier(REGISTER_TXT_FIELD)] != nil, "Textfield should register")
}
func testUnregisterField(){
UNREGISTER_VALIDATOR.registerField(UNREGISTER_TXT_FIELD, rules: UNREGISTER_RULES)
UNREGISTER_VALIDATOR.unregisterField(UNREGISTER_TXT_FIELD)
XCTAssert(UNREGISTER_VALIDATOR.validations[UNREGISTER_TXT_FIELD] == nil, "Textfield should unregister")
XCTAssert(UNREGISTER_VALIDATOR.validations[ObjectIdentifier(UNREGISTER_TXT_FIELD)] == nil, "Textfield should unregister")
}
func testUnregisterError(){

View File

@ -12,7 +12,7 @@
62D1AE221A1E6D4400E4DFF8 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 62D1AE201A1E6D4400E4DFF8 /* Main.storyboard */; };
62D1AE241A1E6D4400E4DFF8 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 62D1AE231A1E6D4400E4DFF8 /* Images.xcassets */; };
62D1AE271A1E6D4400E4DFF8 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 62D1AE251A1E6D4400E4DFF8 /* LaunchScreen.xib */; };
62D9B2561C7C0B2A00BAFCE3 /* ValidationDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62D9B2551C7C0B2A00BAFCE3 /* ValidationDelegate.swift */; settings = {ASSET_TAGS = (); }; };
62D9B2561C7C0B2A00BAFCE3 /* ValidationDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62D9B2551C7C0B2A00BAFCE3 /* ValidationDelegate.swift */; };
7CC1E4CF1C636B4500AF013C /* AlphaRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CC1E4CE1C636B4500AF013C /* AlphaRule.swift */; };
7CC1E4D11C637A7700AF013C /* AlphaNumericRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CC1E4D01C637A7700AF013C /* AlphaNumericRule.swift */; };
7CC1E4D31C637ABC00AF013C /* CharacterSetRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CC1E4D21C637ABC00AF013C /* CharacterSetRule.swift */; };
@ -40,6 +40,7 @@
FB465CFF1B9889EA00398388 /* ZipCodeRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = FB465CEF1B9889EA00398388 /* ZipCodeRule.swift */; };
FB465D001B9889EA00398388 /* ValidationError.swift in Sources */ = {isa = PBXBuildFile; fileRef = FB465CF11B9889EA00398388 /* ValidationError.swift */; };
FB465D011B9889EA00398388 /* Validator.swift in Sources */ = {isa = PBXBuildFile; fileRef = FB465CF21B9889EA00398388 /* Validator.swift */; };
FB51E5B01CD208B8004DE696 /* Validatable.swift in Sources */ = {isa = PBXBuildFile; fileRef = FB51E5AF1CD208B8004DE696 /* Validatable.swift */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@ -126,6 +127,7 @@
FB465CEF1B9889EA00398388 /* ZipCodeRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ZipCodeRule.swift; sourceTree = "<group>"; };
FB465CF11B9889EA00398388 /* ValidationError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ValidationError.swift; sourceTree = "<group>"; };
FB465CF21B9889EA00398388 /* Validator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Validator.swift; sourceTree = "<group>"; };
FB51E5AF1CD208B8004DE696 /* Validatable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Validatable.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@ -290,6 +292,7 @@
62D9B2551C7C0B2A00BAFCE3 /* ValidationDelegate.swift */,
FB465CF11B9889EA00398388 /* ValidationError.swift */,
FB465CF21B9889EA00398388 /* Validator.swift */,
FB51E5AF1CD208B8004DE696 /* Validatable.swift */,
);
path = Core;
sourceTree = "<group>";
@ -498,6 +501,7 @@
FB465D011B9889EA00398388 /* Validator.swift in Sources */,
FB465CFE1B9889EA00398388 /* ValidationRule.swift in Sources */,
FB465CF31B9889EA00398388 /* ConfirmRule.swift in Sources */,
FB51E5B01CD208B8004DE696 /* Validatable.swift in Sources */,
7CC1E4D51C637C8500AF013C /* IPV4Rule.swift in Sources */,
7CC1E4D71C637F6E00AF013C /* ISBNRule.swift in Sources */,
FB465D001B9889EA00398388 /* ValidationError.swift in Sources */,

View File

@ -35,18 +35,22 @@ class ViewController: UIViewController , ValidationDelegate, UITextFieldDelegate
validator.styleTransformers(success:{ (validationRule) -> Void in
print("here")
// clear error label
validationRule.errorLabel?.hidden = true
validationRule.errorLabel?.text = ""
validationRule.textField.layer.borderColor = UIColor.greenColor().CGColor
validationRule.textField.layer.borderWidth = 0.5
}, error:{ (validationError) -> Void in
print("error")
validationError.errorLabel?.hidden = false
validationError.errorLabel?.text = validationError.errorMessage
validationError.textField.layer.borderColor = UIColor.redColor().CGColor
validationError.textField.layer.borderWidth = 1.0
// clear error label
validationRule.errorLabel?.hidden = true
validationRule.errorLabel?.text = ""
if let textField = validationRule.field as? UITextField {
textField.layer.borderColor = UIColor.greenColor().CGColor
textField.layer.borderWidth = 0.5
}
}, error:{ (validationError) -> Void in
print("error")
validationError.errorLabel?.hidden = false
validationError.errorLabel?.text = validationError.errorMessage
if let textField = validationError.field as? UITextField {
textField.layer.borderColor = UIColor.redColor().CGColor
textField.layer.borderWidth = 1.0
}
})
validator.registerField(fullNameTextField, errorLabel: fullNameErrorLabel , rules: [RequiredRule(), FullNameRule()])
@ -71,7 +75,7 @@ class ViewController: UIViewController , ValidationDelegate, UITextFieldDelegate
self.presentViewController(alert, animated: true, completion: nil)
}
func validationFailed(errors:[UITextField:ValidationError]) {
func validationFailed(errors:[(Validatable, ValidationError)]) {
print("Validation FAILED!")
}