Changing to version 2
This commit is contained in:
parent
658c7365c0
commit
abc729aeac
141
README.md
141
README.md
|
|
@ -7,15 +7,15 @@ Swift Validator is a rule-based validation library for Swift.
|
|||
|
||||
## Core Concepts
|
||||
|
||||
* ```UITextField``` + ```ValidationRule``` go into ```Validator```
|
||||
* ```UITextField``` + ```ValidationError``` come out of ```Validator```
|
||||
* ```UITextField``` is registered to ```Validator```
|
||||
* ```Validator``` evaluates ```ValidationRules``` sequentially and stops evaluating when a ```ValidationRule``` fails.
|
||||
* ``UITextField`` + ``ValidationRule`` go into ```Validator``
|
||||
* ``ITextField`` + ``ValidationError`` come out of ```Validator``
|
||||
* ``UITextField`` is registered to ``Validator``
|
||||
* ``Validator`` evaluates ``ValidationRules`` sequentially and stops evaluating when a ``ValidationRule`` fails.
|
||||
* Keys are used to allow field registration in TableViewControllers and complex view hierarchies
|
||||
|
||||
## Quick Start
|
||||
|
||||
Initialize the ```Validator``` by setting a delegate to a View Controller or other object.
|
||||
Initialize the ``Validator`` by setting a delegate to a View Controller or other object.
|
||||
|
||||
```swift
|
||||
|
||||
|
|
@ -33,31 +33,22 @@ Register the fields that you want to validate
|
|||
|
||||
```swift
|
||||
|
||||
var fields:[String] = ["FullName", "Email", "Phone"]
|
||||
// Validation Rules are evaluated from left to right.
|
||||
validator.registerField(fullNameTextField, rules: [RequiredRule(), FullNameRule()])
|
||||
|
||||
// Validation Rules are evaluated from left to right. The first rule is ValidationRuleType.Required the second is ValidationRuleType.FullName.
|
||||
validator.registerFieldByKey(fields[0], textField:nameTextField, rules: [.Required, .FullName])
|
||||
validator.registerFieldByKey(fields[1], textField:emailTextField, rules: [.Required, .Email])
|
||||
validator.registerFieldByKe(fields[2], textField:phoneTextField, rules: [.Required, .PhoneNumber])
|
||||
// You can pass in error labels with your rules
|
||||
|
||||
validator.registerField(emailTextField, errorLabel: emailErrorLabel, rules: [RequiredRule(), EmailRule()])
|
||||
|
||||
// You can validate against other fields
|
||||
validator.registerField(emailConfirmTextField, errorLabel: emailConfirmErrorLabel, rules: [RequiredRule(), EmailRule(), ConfirmationRule(confirmField: emailTextField)])
|
||||
|
||||
// You can now pass in regex and length parameters through overloaded contructors
|
||||
validator.registerField(phoneNumberTextField, errorLabel: phoneNumberErrorLabel, rules: [RequiredRule(), MinLengthRule(length: 9)])
|
||||
validator.registerField(zipcodeTextField, errorLabel: zipcodeErrorLabel, rules: [RequiredRule(), ZipCodeRule()])
|
||||
|
||||
```
|
||||
|
||||
Validate Individual Field
|
||||
|
||||
```swift
|
||||
|
||||
validator.validateFieldByKey(fields[0], delegate:self)
|
||||
|
||||
// ValidationFieldDelegate methods
|
||||
func validationFieldSuccess(key:String, validField:UITextField){
|
||||
validField.backgroundColor = UIColor.greenColor()
|
||||
}
|
||||
|
||||
func validationFieldFailure(key:String, error:ValidationError){
|
||||
println(error.error.description)
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
Validate All Fields
|
||||
|
||||
|
|
@ -104,109 +95,11 @@ class SSNValidation: Validation {
|
|||
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
Add the ```ValidationRuleType.SocialSecurity```
|
||||
|
||||
```swift
|
||||
|
||||
enum ValidationRuleType {
|
||||
case Required,
|
||||
Email,
|
||||
Password,
|
||||
MinLength,
|
||||
MaxLength,
|
||||
ZipCode,
|
||||
PhoneNumber,
|
||||
FullName,
|
||||
SocialSecurity // Added to the ValidationRuleTypes
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
Add the ```ValidationErrorType.SocialSecurity``` and ```description()```
|
||||
|
||||
```swift
|
||||
|
||||
enum ValidationErrorType {
|
||||
case Required,
|
||||
Email,
|
||||
Password,
|
||||
MinLength,
|
||||
MaxLength,
|
||||
ZipCode,
|
||||
PhoneNumber,
|
||||
FullName,
|
||||
SocialSecurity, // Added to the ValidationErrorTypes
|
||||
NoError
|
||||
|
||||
func description() -> String {
|
||||
switch self {
|
||||
case .Required:
|
||||
return "Required field"
|
||||
case .Email:
|
||||
return "Must be a valid email"
|
||||
case .MaxLength:
|
||||
return "This field should be less than"
|
||||
case .ZipCode:
|
||||
return "5 digit zipcode"
|
||||
case .PhoneNumber:
|
||||
return "10 digit phone number"
|
||||
case .Password:
|
||||
return "Must be at least 8 characters"
|
||||
case .FullName:
|
||||
return "Provide a first & last name"
|
||||
// Adding the desired error message
|
||||
case .SocialSecurity:
|
||||
return "SSN is XXX-XX-XXXX"
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
```
|
||||
Register the ```SSNValidation``` with the ```ValidationFactory```
|
||||
|
||||
```swift
|
||||
|
||||
class ValidationFactory {
|
||||
class func validationForRule(rule:ValidationRuleType) -> Validation {
|
||||
switch rule {
|
||||
case .Required:
|
||||
return RequiredValidation()
|
||||
case .Email:
|
||||
return EmailValidation()
|
||||
case .MinLength:
|
||||
return MinLengthValidation()
|
||||
case .MaxLength:
|
||||
return MaxLengthValidation()
|
||||
case .PhoneNumber:
|
||||
return PhoneNumberValidation()
|
||||
case .ZipCode:
|
||||
return ZipCodeValidation()
|
||||
case .FullName:
|
||||
return FullNameValidation()
|
||||
// Add Validation to allow Factory to create one on the fly for you
|
||||
case .SocialSecurity:
|
||||
return SSNValidation()
|
||||
default:
|
||||
return RequiredValidation()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
Credits
|
||||
-------
|
||||
|
||||
Swift Validator is written and maintained by Jeff Potter [@jpotts18](http://twitter.com/jpotts18) and friends.
|
||||
|
||||
Currently funded and maintained by [RingSeven](http://ringseven.com)
|
||||
|
||||

|
||||
|
||||
## Contributing
|
||||
|
||||
1. [Fork it](https://github.com/jpotts18/swift-validator/fork)
|
||||
|
|
|
|||
|
|
@ -7,27 +7,23 @@
|
|||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
628637261AAA474B00BC8FCF /* MinLengthRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 628637251AAA474B00BC8FCF /* MinLengthRule.swift */; };
|
||||
628637281AAA49E300BC8FCF /* ConfirmRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 628637271AAA49E300BC8FCF /* ConfirmRule.swift */; };
|
||||
62D1AE1D1A1E6D4400E4DFF8 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62D1AE1C1A1E6D4400E4DFF8 /* AppDelegate.swift */; };
|
||||
62D1AE1F1A1E6D4400E4DFF8 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62D1AE1E1A1E6D4400E4DFF8 /* ViewController.swift */; };
|
||||
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 */; };
|
||||
62D1AE331A1E6D4500E4DFF8 /* ValidatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62D1AE321A1E6D4500E4DFF8 /* ValidatorTests.swift */; };
|
||||
62D1AE3E1A1E6FEF00E4DFF8 /* FullNameValidation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62D1AE3D1A1E6FEF00E4DFF8 /* FullNameValidation.swift */; };
|
||||
62D1AE491A1E6FF800E4DFF8 /* EmailValidation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62D1AE3F1A1E6FF800E4DFF8 /* EmailValidation.swift */; };
|
||||
62D1AE4A1A1E6FF800E4DFF8 /* MaxLengthValidation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62D1AE401A1E6FF800E4DFF8 /* MaxLengthValidation.swift */; };
|
||||
62D1AE4B1A1E6FF800E4DFF8 /* MinLengthValidation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62D1AE411A1E6FF800E4DFF8 /* MinLengthValidation.swift */; };
|
||||
62D1AE4C1A1E6FF800E4DFF8 /* PhoneNumberValidation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62D1AE421A1E6FF800E4DFF8 /* PhoneNumberValidation.swift */; };
|
||||
62D1AE4D1A1E6FF800E4DFF8 /* RequiredValidation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62D1AE431A1E6FF800E4DFF8 /* RequiredValidation.swift */; };
|
||||
62D1AE4E1A1E6FF800E4DFF8 /* Validation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62D1AE441A1E6FF800E4DFF8 /* Validation.swift */; };
|
||||
62D1AE4F1A1E6FF800E4DFF8 /* ValidationError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62D1AE451A1E6FF800E4DFF8 /* ValidationError.swift */; };
|
||||
62D1AE501A1E6FF800E4DFF8 /* ValidationErrorType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62D1AE461A1E6FF800E4DFF8 /* ValidationErrorType.swift */; };
|
||||
62D1AE511A1E6FF800E4DFF8 /* ValidationFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62D1AE471A1E6FF800E4DFF8 /* ValidationFactory.swift */; };
|
||||
62D1AE521A1E6FF800E4DFF8 /* ValidationRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62D1AE481A1E6FF800E4DFF8 /* ValidationRule.swift */; };
|
||||
62D1AE571A1E700200E4DFF8 /* ValidationRuleType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62D1AE531A1E700200E4DFF8 /* ValidationRuleType.swift */; };
|
||||
62D1AE581A1E700200E4DFF8 /* Validator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62D1AE541A1E700200E4DFF8 /* Validator.swift */; };
|
||||
62D1AE591A1E700200E4DFF8 /* ZipCodeValidation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62D1AE551A1E700200E4DFF8 /* ZipCodeValidation.swift */; };
|
||||
62D1AE5A1A1E700200E4DFF8 /* PasswordValidation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62D1AE561A1E700200E4DFF8 /* PasswordValidation.swift */; };
|
||||
62DC8D651AAA42520095DFA7 /* Rule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62DC8D641AAA42520095DFA7 /* Rule.swift */; };
|
||||
62DC8D681AAA42920095DFA7 /* FullNameRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62DC8D671AAA42920095DFA7 /* FullNameRule.swift */; };
|
||||
62DC8D6C1AAA42CE0095DFA7 /* EmailRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62DC8D691AAA42CE0095DFA7 /* EmailRule.swift */; };
|
||||
62DC8D6D1AAA42CE0095DFA7 /* RequiredRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62DC8D6A1AAA42CE0095DFA7 /* RequiredRule.swift */; };
|
||||
62DC8D6E1AAA42CE0095DFA7 /* PasswordRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62DC8D6B1AAA42CE0095DFA7 /* PasswordRule.swift */; };
|
||||
62DC8D711AAA43110095DFA7 /* ZipCodeRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62DC8D701AAA43110095DFA7 /* ZipCodeRule.swift */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
|
|
@ -41,6 +37,8 @@
|
|||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
628637251AAA474B00BC8FCF /* MinLengthRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MinLengthRule.swift; sourceTree = "<group>"; };
|
||||
628637271AAA49E300BC8FCF /* ConfirmRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConfirmRule.swift; sourceTree = "<group>"; };
|
||||
62D1AE171A1E6D4400E4DFF8 /* Validator.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Validator.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
62D1AE1B1A1E6D4400E4DFF8 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
62D1AE1C1A1E6D4400E4DFF8 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||
|
|
@ -51,21 +49,15 @@
|
|||
62D1AE2C1A1E6D4500E4DFF8 /* ValidatorTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ValidatorTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
62D1AE311A1E6D4500E4DFF8 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
62D1AE321A1E6D4500E4DFF8 /* ValidatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ValidatorTests.swift; sourceTree = "<group>"; };
|
||||
62D1AE3D1A1E6FEF00E4DFF8 /* FullNameValidation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FullNameValidation.swift; sourceTree = "<group>"; };
|
||||
62D1AE3F1A1E6FF800E4DFF8 /* EmailValidation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EmailValidation.swift; sourceTree = "<group>"; };
|
||||
62D1AE401A1E6FF800E4DFF8 /* MaxLengthValidation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MaxLengthValidation.swift; sourceTree = "<group>"; };
|
||||
62D1AE411A1E6FF800E4DFF8 /* MinLengthValidation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MinLengthValidation.swift; sourceTree = "<group>"; };
|
||||
62D1AE421A1E6FF800E4DFF8 /* PhoneNumberValidation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PhoneNumberValidation.swift; sourceTree = "<group>"; };
|
||||
62D1AE431A1E6FF800E4DFF8 /* RequiredValidation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RequiredValidation.swift; sourceTree = "<group>"; };
|
||||
62D1AE441A1E6FF800E4DFF8 /* Validation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Validation.swift; sourceTree = "<group>"; };
|
||||
62D1AE451A1E6FF800E4DFF8 /* ValidationError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ValidationError.swift; sourceTree = "<group>"; };
|
||||
62D1AE461A1E6FF800E4DFF8 /* ValidationErrorType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ValidationErrorType.swift; sourceTree = "<group>"; };
|
||||
62D1AE471A1E6FF800E4DFF8 /* ValidationFactory.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ValidationFactory.swift; sourceTree = "<group>"; };
|
||||
62D1AE481A1E6FF800E4DFF8 /* ValidationRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ValidationRule.swift; sourceTree = "<group>"; };
|
||||
62D1AE531A1E700200E4DFF8 /* ValidationRuleType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ValidationRuleType.swift; sourceTree = "<group>"; };
|
||||
62D1AE541A1E700200E4DFF8 /* Validator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Validator.swift; sourceTree = "<group>"; };
|
||||
62D1AE551A1E700200E4DFF8 /* ZipCodeValidation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ZipCodeValidation.swift; sourceTree = "<group>"; };
|
||||
62D1AE561A1E700200E4DFF8 /* PasswordValidation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PasswordValidation.swift; sourceTree = "<group>"; };
|
||||
62DC8D641AAA42520095DFA7 /* Rule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Rule.swift; sourceTree = "<group>"; };
|
||||
62DC8D671AAA42920095DFA7 /* FullNameRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FullNameRule.swift; sourceTree = "<group>"; };
|
||||
62DC8D691AAA42CE0095DFA7 /* EmailRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EmailRule.swift; sourceTree = "<group>"; };
|
||||
62DC8D6A1AAA42CE0095DFA7 /* RequiredRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RequiredRule.swift; sourceTree = "<group>"; };
|
||||
62DC8D6B1AAA42CE0095DFA7 /* PasswordRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PasswordRule.swift; sourceTree = "<group>"; };
|
||||
62DC8D701AAA43110095DFA7 /* ZipCodeRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ZipCodeRule.swift; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
|
|
@ -89,8 +81,8 @@
|
|||
626BE5EE1A9B8EC600FE6D5C /* Swift-Validator */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
62DC8D661AAA42700095DFA7 /* Rules */,
|
||||
62D1AE3C1A1E6FAF00E4DFF8 /* Core */,
|
||||
62D1AE5B1A1E701B00E4DFF8 /* Validations */,
|
||||
);
|
||||
name = "Swift-Validator";
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -155,30 +147,26 @@
|
|||
62D1AE3C1A1E6FAF00E4DFF8 /* Core */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
62D1AE531A1E700200E4DFF8 /* ValidationRuleType.swift */,
|
||||
62D1AE541A1E700200E4DFF8 /* Validator.swift */,
|
||||
62D1AE451A1E6FF800E4DFF8 /* ValidationError.swift */,
|
||||
62D1AE461A1E6FF800E4DFF8 /* ValidationErrorType.swift */,
|
||||
62D1AE471A1E6FF800E4DFF8 /* ValidationFactory.swift */,
|
||||
62D1AE481A1E6FF800E4DFF8 /* ValidationRule.swift */,
|
||||
62D1AE441A1E6FF800E4DFF8 /* Validation.swift */,
|
||||
);
|
||||
name = Core;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
62D1AE5B1A1E701B00E4DFF8 /* Validations */ = {
|
||||
62DC8D661AAA42700095DFA7 /* Rules */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
62D1AE3D1A1E6FEF00E4DFF8 /* FullNameValidation.swift */,
|
||||
62D1AE421A1E6FF800E4DFF8 /* PhoneNumberValidation.swift */,
|
||||
62D1AE431A1E6FF800E4DFF8 /* RequiredValidation.swift */,
|
||||
62D1AE3F1A1E6FF800E4DFF8 /* EmailValidation.swift */,
|
||||
62D1AE411A1E6FF800E4DFF8 /* MinLengthValidation.swift */,
|
||||
62D1AE401A1E6FF800E4DFF8 /* MaxLengthValidation.swift */,
|
||||
62D1AE561A1E700200E4DFF8 /* PasswordValidation.swift */,
|
||||
62D1AE551A1E700200E4DFF8 /* ZipCodeValidation.swift */,
|
||||
628637251AAA474B00BC8FCF /* MinLengthRule.swift */,
|
||||
62DC8D641AAA42520095DFA7 /* Rule.swift */,
|
||||
62DC8D691AAA42CE0095DFA7 /* EmailRule.swift */,
|
||||
62DC8D6A1AAA42CE0095DFA7 /* RequiredRule.swift */,
|
||||
62DC8D6B1AAA42CE0095DFA7 /* PasswordRule.swift */,
|
||||
62DC8D671AAA42920095DFA7 /* FullNameRule.swift */,
|
||||
62DC8D701AAA43110095DFA7 /* ZipCodeRule.swift */,
|
||||
628637271AAA49E300BC8FCF /* ConfirmRule.swift */,
|
||||
);
|
||||
name = Validations;
|
||||
name = Rules;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
|
@ -281,23 +269,19 @@
|
|||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
62D1AE4C1A1E6FF800E4DFF8 /* PhoneNumberValidation.swift in Sources */,
|
||||
62D1AE5A1A1E700200E4DFF8 /* PasswordValidation.swift in Sources */,
|
||||
62DC8D681AAA42920095DFA7 /* FullNameRule.swift in Sources */,
|
||||
62D1AE4F1A1E6FF800E4DFF8 /* ValidationError.swift in Sources */,
|
||||
62D1AE3E1A1E6FEF00E4DFF8 /* FullNameValidation.swift in Sources */,
|
||||
62D1AE4B1A1E6FF800E4DFF8 /* MinLengthValidation.swift in Sources */,
|
||||
62DC8D6E1AAA42CE0095DFA7 /* PasswordRule.swift in Sources */,
|
||||
62DC8D6C1AAA42CE0095DFA7 /* EmailRule.swift in Sources */,
|
||||
628637281AAA49E300BC8FCF /* ConfirmRule.swift in Sources */,
|
||||
62DC8D651AAA42520095DFA7 /* Rule.swift in Sources */,
|
||||
62D1AE1F1A1E6D4400E4DFF8 /* ViewController.swift in Sources */,
|
||||
62D1AE4E1A1E6FF800E4DFF8 /* Validation.swift in Sources */,
|
||||
62DC8D6D1AAA42CE0095DFA7 /* RequiredRule.swift in Sources */,
|
||||
62D1AE1D1A1E6D4400E4DFF8 /* AppDelegate.swift in Sources */,
|
||||
62D1AE581A1E700200E4DFF8 /* Validator.swift in Sources */,
|
||||
62D1AE501A1E6FF800E4DFF8 /* ValidationErrorType.swift in Sources */,
|
||||
62D1AE491A1E6FF800E4DFF8 /* EmailValidation.swift in Sources */,
|
||||
62D1AE511A1E6FF800E4DFF8 /* ValidationFactory.swift in Sources */,
|
||||
62D1AE591A1E700200E4DFF8 /* ZipCodeValidation.swift in Sources */,
|
||||
62D1AE571A1E700200E4DFF8 /* ValidationRuleType.swift in Sources */,
|
||||
628637261AAA474B00BC8FCF /* MinLengthRule.swift in Sources */,
|
||||
62DC8D711AAA43110095DFA7 /* ZipCodeRule.swift in Sources */,
|
||||
62D1AE521A1E6FF800E4DFF8 /* ValidationRule.swift in Sources */,
|
||||
62D1AE4A1A1E6FF800E4DFF8 /* MaxLengthValidation.swift in Sources */,
|
||||
62D1AE4D1A1E6FF800E4DFF8 /* RequiredValidation.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -1,7 +1,8 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="6250" systemVersion="14A389" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="vXZ-lx-hvc">
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="6254" systemVersion="14B25" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="vXZ-lx-hvc">
|
||||
<dependencies>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6244"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6247"/>
|
||||
<capability name="Alignment constraints with different attributes" minToolsVersion="5.1"/>
|
||||
<capability name="Constraints to layout margins" minToolsVersion="6.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
|
|
@ -23,11 +24,6 @@
|
|||
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="Darth Vader" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="3uK-Qz-rLB">
|
||||
<rect key="frame" x="0.0" y="-30" width="97" height="30"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="14"/>
|
||||
<textInputTraits key="textInputTraits"/>
|
||||
</textField>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Email" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="MOa-Y4-nDo">
|
||||
<rect key="frame" x="0.0" y="-21" width="42" height="21"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
|
|
@ -39,7 +35,7 @@
|
|||
<fontDescription key="fontDescription" type="system" pointSize="14"/>
|
||||
<textInputTraits key="textInputTraits"/>
|
||||
</textField>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Phone Number" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Gjm-Ww-AYk">
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Phone" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Gjm-Ww-AYk">
|
||||
<rect key="frame" x="0.0" y="-21" width="42" height="21"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
|
||||
|
|
@ -133,6 +129,45 @@
|
|||
</mask>
|
||||
</variation>
|
||||
</label>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Email Confirm" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="bLY-f8-5zf">
|
||||
<rect key="frame" x="0.0" y="-21" width="42" height="21"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="darth@deathstar.com" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="O9u-O8-mPB">
|
||||
<rect key="frame" x="0.0" y="-30" width="97" height="30"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="14"/>
|
||||
<textInputTraits key="textInputTraits"/>
|
||||
</textField>
|
||||
<label hidden="YES" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Required" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="K92-ww-iP3">
|
||||
<rect key="frame" x="0.0" y="-21" width="42" height="21"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" relation="greaterThanOrEqual" constant="227" id="SdK-o6-MXe"/>
|
||||
<constraint firstAttribute="height" relation="greaterThanOrEqual" constant="21" id="bi4-dv-zcg"/>
|
||||
<constraint firstAttribute="height" constant="21" id="fjW-er-ghM"/>
|
||||
<constraint firstAttribute="width" constant="227" id="hpm-mc-xeq"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="13"/>
|
||||
<color key="textColor" red="1" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
<variation key="default">
|
||||
<mask key="constraints">
|
||||
<exclude reference="fjW-er-ghM"/>
|
||||
<exclude reference="hpm-mc-xeq"/>
|
||||
<exclude reference="bi4-dv-zcg"/>
|
||||
<exclude reference="SdK-o6-MXe"/>
|
||||
</mask>
|
||||
</variation>
|
||||
<variation key="heightClass=regular-widthClass=compact">
|
||||
<mask key="constraints">
|
||||
<include reference="fjW-er-ghM"/>
|
||||
<include reference="hpm-mc-xeq"/>
|
||||
<include reference="bi4-dv-zcg"/>
|
||||
<include reference="SdK-o6-MXe"/>
|
||||
</mask>
|
||||
</variation>
|
||||
</label>
|
||||
<label hidden="YES" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Required" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="pon-eT-yrd">
|
||||
<rect key="frame" x="0.0" y="-21" width="42" height="21"/>
|
||||
<constraints>
|
||||
|
|
@ -170,6 +205,11 @@
|
|||
<action selector="submitTapped:" destination="vXZ-lx-hvc" eventType="touchUpInside" id="wmP-d4-6hM"/>
|
||||
</connections>
|
||||
</button>
|
||||
<textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="Darth Vader" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="3uK-Qz-rLB">
|
||||
<rect key="frame" x="0.0" y="-30" width="97" height="30"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="14"/>
|
||||
<textInputTraits key="textInputTraits"/>
|
||||
</textField>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
|
||||
<constraints>
|
||||
|
|
@ -189,16 +229,17 @@
|
|||
<variation key="heightClass=regular-widthClass=compact" constant="20"/>
|
||||
</constraint>
|
||||
<constraint firstItem="Zu1-QS-1Yk" firstAttribute="leading" secondItem="kh9-bI-dsS" secondAttribute="leadingMargin" id="B28-e9-frX"/>
|
||||
<constraint firstItem="O9u-O8-mPB" firstAttribute="top" secondItem="bLY-f8-5zf" secondAttribute="bottom" constant="8" id="DtP-3P-vpf"/>
|
||||
<constraint firstItem="Zu1-QS-1Yk" firstAttribute="trailing" secondItem="kh9-bI-dsS" secondAttribute="trailingMargin" id="Egg-Ya-137"/>
|
||||
<constraint firstItem="ibf-gq-p2X" firstAttribute="trailing" secondItem="kh9-bI-dsS" secondAttribute="trailingMargin" id="H9S-E2-xEW"/>
|
||||
<constraint firstItem="3uK-Qz-rLB" firstAttribute="leading" secondItem="kh9-bI-dsS" secondAttribute="leadingMargin" id="Ion-9h-zfc"/>
|
||||
<constraint firstItem="qLN-YJ-gUx" firstAttribute="leading" secondItem="kh9-bI-dsS" secondAttribute="leadingMargin" id="K5d-es-d8h"/>
|
||||
<constraint firstItem="K92-ww-iP3" firstAttribute="top" secondItem="ibf-gq-p2X" secondAttribute="bottom" constant="25" id="LFO-jd-axU"/>
|
||||
<constraint firstItem="Gw5-ME-8qn" firstAttribute="leading" secondItem="kh9-bI-dsS" secondAttribute="leadingMargin" id="M9f-Bp-Gbg"/>
|
||||
<constraint firstItem="Gjm-Ww-AYk" firstAttribute="top" secondItem="ibf-gq-p2X" secondAttribute="bottom" constant="18" id="Moy-q7-oUR">
|
||||
<variation key="heightClass=regular-widthClass=compact" constant="20"/>
|
||||
</constraint>
|
||||
<constraint firstItem="5Yi-nP-Hf3" firstAttribute="top" secondItem="jyV-Pf-zRb" secondAttribute="bottom" constant="8" id="OdB-kn-E8t"/>
|
||||
<constraint firstItem="Gjm-Ww-AYk" firstAttribute="top" secondItem="O9u-O8-mPB" secondAttribute="bottom" constant="21" id="PEI-qV-ay9"/>
|
||||
<constraint firstItem="2or-KE-2NU" firstAttribute="leading" secondItem="kh9-bI-dsS" secondAttribute="leadingMargin" id="PaQ-6i-9mo"/>
|
||||
<constraint firstItem="O9u-O8-mPB" firstAttribute="leading" secondItem="kh9-bI-dsS" secondAttribute="leadingMargin" id="T1M-HW-h60"/>
|
||||
<constraint firstItem="3uK-Qz-rLB" firstAttribute="top" secondItem="5Yi-nP-Hf3" secondAttribute="bottom" constant="8" id="VDP-DY-jUh"/>
|
||||
<constraint firstItem="qLN-YJ-gUx" firstAttribute="top" secondItem="F6l-Qg-562" secondAttribute="bottom" constant="8" id="VDe-WO-sJU"/>
|
||||
<constraint firstItem="ibf-gq-p2X" firstAttribute="top" secondItem="MOa-Y4-nDo" secondAttribute="bottom" constant="9" id="VWf-RY-YhF">
|
||||
|
|
@ -209,6 +250,7 @@
|
|||
<constraint firstItem="khR-OB-bgx" firstAttribute="leading" secondItem="kh9-bI-dsS" secondAttribute="leadingMargin" id="bud-iX-j0f"/>
|
||||
<constraint firstItem="Gjm-Ww-AYk" firstAttribute="leading" secondItem="kh9-bI-dsS" secondAttribute="leadingMargin" id="cNA-Yf-qTv"/>
|
||||
<constraint firstItem="qLN-YJ-gUx" firstAttribute="top" secondItem="Gjm-Ww-AYk" secondAttribute="bottom" constant="8" id="d08-t5-VT0"/>
|
||||
<constraint firstItem="O9u-O8-mPB" firstAttribute="trailing" secondItem="kh9-bI-dsS" secondAttribute="trailingMargin" id="ds9-gC-21F"/>
|
||||
<constraint firstItem="Zu1-QS-1Yk" firstAttribute="top" secondItem="2or-KE-2NU" secondAttribute="bottom" constant="9" id="eAd-Wu-obj">
|
||||
<variation key="heightClass=regular-widthClass=compact" constant="8"/>
|
||||
</constraint>
|
||||
|
|
@ -217,19 +259,19 @@
|
|||
<variation key="heightClass=regular-widthClass=compact" constant="20"/>
|
||||
</constraint>
|
||||
<constraint firstItem="v4N-fz-1u1" firstAttribute="trailing" secondItem="kh9-bI-dsS" secondAttribute="trailingMargin" id="hpD-Om-vt4"/>
|
||||
<constraint firstItem="O9u-O8-mPB" firstAttribute="top" secondItem="K92-ww-iP3" secondAttribute="bottom" constant="8" id="htl-Vj-x3w"/>
|
||||
<constraint firstItem="Zu1-QS-1Yk" firstAttribute="top" secondItem="pon-eT-yrd" secondAttribute="bottom" constant="9" id="k2e-YN-zp4">
|
||||
<variation key="heightClass=regular-widthClass=compact" constant="8"/>
|
||||
</constraint>
|
||||
<constraint firstItem="F6l-Qg-562" firstAttribute="top" secondItem="ibf-gq-p2X" secondAttribute="bottom" constant="18" id="oYt-uZ-XMO">
|
||||
<variation key="heightClass=regular-widthClass=compact" constant="20"/>
|
||||
</constraint>
|
||||
<constraint firstItem="bLY-f8-5zf" firstAttribute="leading" secondItem="kh9-bI-dsS" secondAttribute="leadingMargin" id="qWu-f4-OGv"/>
|
||||
<constraint firstItem="3uK-Qz-rLB" firstAttribute="top" secondItem="khR-OB-bgx" secondAttribute="bottom" constant="8" id="rRl-bj-wIm"/>
|
||||
<constraint firstItem="bLY-f8-5zf" firstAttribute="top" secondItem="ibf-gq-p2X" secondAttribute="bottom" constant="25" id="sh3-oU-dEE"/>
|
||||
<constraint firstItem="3uK-Qz-rLB" firstAttribute="trailing" secondItem="kh9-bI-dsS" secondAttribute="trailingMargin" id="t8X-0Q-RPA"/>
|
||||
<constraint firstItem="K92-ww-iP3" firstAttribute="trailing" secondItem="kh9-bI-dsS" secondAttribute="trailingMargin" id="wny-JX-bf3"/>
|
||||
</constraints>
|
||||
<variation key="default">
|
||||
<mask key="subviews">
|
||||
<exclude reference="khR-OB-bgx"/>
|
||||
<exclude reference="3uK-Qz-rLB"/>
|
||||
<exclude reference="MOa-Y4-nDo"/>
|
||||
<exclude reference="ibf-gq-p2X"/>
|
||||
<exclude reference="Gjm-Ww-AYk"/>
|
||||
|
|
@ -239,8 +281,12 @@
|
|||
<exclude reference="5Yi-nP-Hf3"/>
|
||||
<exclude reference="v4N-fz-1u1"/>
|
||||
<exclude reference="F6l-Qg-562"/>
|
||||
<exclude reference="bLY-f8-5zf"/>
|
||||
<exclude reference="O9u-O8-mPB"/>
|
||||
<exclude reference="K92-ww-iP3"/>
|
||||
<exclude reference="pon-eT-yrd"/>
|
||||
<exclude reference="Gw5-ME-8qn"/>
|
||||
<exclude reference="3uK-Qz-rLB"/>
|
||||
</mask>
|
||||
<mask key="constraints">
|
||||
<exclude reference="bud-iX-j0f"/>
|
||||
|
|
@ -259,16 +305,23 @@
|
|||
<exclude reference="aeN-FP-LX6"/>
|
||||
<exclude reference="55u-lk-Vl8"/>
|
||||
<exclude reference="OdB-kn-E8t"/>
|
||||
<exclude reference="Moy-q7-oUR"/>
|
||||
<exclude reference="cNA-Yf-qTv"/>
|
||||
<exclude reference="7J7-45-P5G"/>
|
||||
<exclude reference="hpD-Om-vt4"/>
|
||||
<exclude reference="qWu-f4-OGv"/>
|
||||
<exclude reference="sh3-oU-dEE"/>
|
||||
<exclude reference="DtP-3P-vpf"/>
|
||||
<exclude reference="T1M-HW-h60"/>
|
||||
<exclude reference="ds9-gC-21F"/>
|
||||
<exclude reference="htl-Vj-x3w"/>
|
||||
<exclude reference="LFO-jd-axU"/>
|
||||
<exclude reference="wny-JX-bf3"/>
|
||||
<exclude reference="PEI-qV-ay9"/>
|
||||
<exclude reference="cNA-Yf-qTv"/>
|
||||
<exclude reference="60N-Dv-oSw"/>
|
||||
<exclude reference="K5d-es-d8h"/>
|
||||
<exclude reference="VDe-WO-sJU"/>
|
||||
<exclude reference="d08-t5-VT0"/>
|
||||
<exclude reference="7Ce-Df-SWx"/>
|
||||
<exclude reference="oYt-uZ-XMO"/>
|
||||
<exclude reference="A7P-r9-8FC"/>
|
||||
<exclude reference="PaQ-6i-9mo"/>
|
||||
<exclude reference="B28-e9-frX"/>
|
||||
|
|
@ -284,7 +337,6 @@
|
|||
<variation key="heightClass=regular-widthClass=compact">
|
||||
<mask key="subviews">
|
||||
<include reference="khR-OB-bgx"/>
|
||||
<include reference="3uK-Qz-rLB"/>
|
||||
<include reference="MOa-Y4-nDo"/>
|
||||
<include reference="ibf-gq-p2X"/>
|
||||
<include reference="Gjm-Ww-AYk"/>
|
||||
|
|
@ -294,8 +346,12 @@
|
|||
<include reference="5Yi-nP-Hf3"/>
|
||||
<include reference="v4N-fz-1u1"/>
|
||||
<include reference="F6l-Qg-562"/>
|
||||
<include reference="bLY-f8-5zf"/>
|
||||
<include reference="O9u-O8-mPB"/>
|
||||
<include reference="K92-ww-iP3"/>
|
||||
<include reference="pon-eT-yrd"/>
|
||||
<include reference="Gw5-ME-8qn"/>
|
||||
<include reference="3uK-Qz-rLB"/>
|
||||
</mask>
|
||||
<mask key="constraints">
|
||||
<include reference="bud-iX-j0f"/>
|
||||
|
|
@ -314,16 +370,23 @@
|
|||
<include reference="aeN-FP-LX6"/>
|
||||
<include reference="55u-lk-Vl8"/>
|
||||
<include reference="OdB-kn-E8t"/>
|
||||
<include reference="Moy-q7-oUR"/>
|
||||
<include reference="cNA-Yf-qTv"/>
|
||||
<include reference="7J7-45-P5G"/>
|
||||
<include reference="hpD-Om-vt4"/>
|
||||
<include reference="qWu-f4-OGv"/>
|
||||
<include reference="sh3-oU-dEE"/>
|
||||
<include reference="DtP-3P-vpf"/>
|
||||
<include reference="T1M-HW-h60"/>
|
||||
<include reference="ds9-gC-21F"/>
|
||||
<include reference="htl-Vj-x3w"/>
|
||||
<include reference="LFO-jd-axU"/>
|
||||
<include reference="wny-JX-bf3"/>
|
||||
<include reference="PEI-qV-ay9"/>
|
||||
<include reference="cNA-Yf-qTv"/>
|
||||
<include reference="60N-Dv-oSw"/>
|
||||
<include reference="K5d-es-d8h"/>
|
||||
<include reference="VDe-WO-sJU"/>
|
||||
<include reference="d08-t5-VT0"/>
|
||||
<include reference="7Ce-Df-SWx"/>
|
||||
<include reference="oYt-uZ-XMO"/>
|
||||
<include reference="A7P-r9-8FC"/>
|
||||
<include reference="PaQ-6i-9mo"/>
|
||||
<include reference="B28-e9-frX"/>
|
||||
|
|
@ -338,6 +401,8 @@
|
|||
</variation>
|
||||
</view>
|
||||
<connections>
|
||||
<outlet property="emailConfirmErrorLabel" destination="K92-ww-iP3" id="EAZ-PN-mPh"/>
|
||||
<outlet property="emailConfirmTextField" destination="O9u-O8-mPB" id="gsp-WL-cSi"/>
|
||||
<outlet property="emailErrorLabel" destination="v4N-fz-1u1" id="aOl-vh-2bv"/>
|
||||
<outlet property="emailTextField" destination="ibf-gq-p2X" id="th5-OF-xXo"/>
|
||||
<outlet property="fullNameErrorLabel" destination="5Yi-nP-Hf3" id="OUq-Yl-ryr"/>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,32 @@
|
|||
//
|
||||
// ConfirmRule.swift
|
||||
// Validator
|
||||
//
|
||||
// Created by Jeff Potter on 3/6/15.
|
||||
// Copyright (c) 2015 jpotts18. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import UIKit
|
||||
|
||||
class ConfirmationRule: Rule {
|
||||
|
||||
let confirmField: UITextField
|
||||
|
||||
init(confirmField: UITextField) {
|
||||
self.confirmField = confirmField
|
||||
}
|
||||
|
||||
func validate(value: String) -> Bool {
|
||||
if self.confirmField.text == value {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func errorMessage() -> String {
|
||||
return "This field does not match"
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
//
|
||||
// EmailValidation.swift
|
||||
// Pingo
|
||||
//
|
||||
// Created by Jeff Potter on 11/11/14.
|
||||
// Copyright (c) 2014 Byron Mackay. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
class EmailRule: Rule {
|
||||
|
||||
let REGEX = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,6}"
|
||||
|
||||
init(){}
|
||||
|
||||
init(regex:String){
|
||||
self.REGEX = regex
|
||||
}
|
||||
|
||||
var message:String {
|
||||
return "Must be a valid email address"
|
||||
}
|
||||
|
||||
func validate(value:String) -> Bool {
|
||||
|
||||
if let emailTest = NSPredicate(format: "SELF MATCHES %@", REGEX) {
|
||||
if emailTest.evaluateWithObject(value) {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func errorMessage() -> String {
|
||||
return self.message
|
||||
}
|
||||
}
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
//
|
||||
// EmailValidation.swift
|
||||
// Pingo
|
||||
//
|
||||
// Created by Jeff Potter on 11/11/14.
|
||||
// Copyright (c) 2014 Byron Mackay. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
class EmailValidation: Validation {
|
||||
|
||||
let EMAIL_REGEX = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,6}"
|
||||
|
||||
func validate(value:String) -> (Bool, ValidationErrorType) {
|
||||
|
||||
if let emailTest = NSPredicate(format: "SELF MATCHES %@", EMAIL_REGEX) {
|
||||
if emailTest.evaluateWithObject(value) {
|
||||
return (true, .NoError)
|
||||
} else {
|
||||
return (false,.Email)
|
||||
}
|
||||
}
|
||||
return (false, .Email)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
//
|
||||
// FullNameValidation.swift
|
||||
// Pingo
|
||||
//
|
||||
// Created by Jeff Potter on 11/19/14.
|
||||
// Copyright (c) 2014 Byron Mackay. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
|
||||
class FullNameRule : Rule {
|
||||
|
||||
var message:String {
|
||||
return "Please provide a first & last name"
|
||||
}
|
||||
|
||||
func validate(value:String) -> Bool {
|
||||
|
||||
var nameArray:[String] = split(value) { $0 == " " }
|
||||
if nameArray.count >= 2 {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func errorMessage() -> String {
|
||||
return message
|
||||
}
|
||||
}
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
//
|
||||
// FullNameValidation.swift
|
||||
// Pingo
|
||||
//
|
||||
// Created by Jeff Potter on 11/19/14.
|
||||
// Copyright (c) 2014 Byron Mackay. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
|
||||
class FullNameValidation : Validation {
|
||||
|
||||
func validate(value:String) -> (Bool, ValidationErrorType) {
|
||||
|
||||
var nameArray:[String] = split(value) { $0 == " " }
|
||||
if nameArray.count == 2 {
|
||||
return (true, .NoError)
|
||||
}
|
||||
return (false, .FullName)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
//
|
||||
// MaxLengthValidation.swift
|
||||
// Pingo
|
||||
//
|
||||
// Created by Jeff Potter on 11/11/14.
|
||||
// Copyright (c) 2014 Byron Mackay. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
class MaxLengthValidation: Validation {
|
||||
let DEFAULT_MAX_LENGTH = 25
|
||||
|
||||
func validate(value: String) -> (Bool, ValidationErrorType) {
|
||||
if countElements(value) > DEFAULT_MAX_LENGTH {
|
||||
return (false, .MaxLength)
|
||||
}
|
||||
return (true, .NoError)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
//
|
||||
// LengthRule.swift
|
||||
// Validator
|
||||
//
|
||||
// Created by Jeff Potter on 3/6/15.
|
||||
// Copyright (c) 2015 jpotts18. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
|
||||
class MinLengthRule : Rule {
|
||||
|
||||
let DEFAULT_MIN_LENGTH:Int = 3
|
||||
|
||||
init(){}
|
||||
|
||||
init(length:Int){
|
||||
self.DEFAULT_MIN_LENGTH = length
|
||||
}
|
||||
|
||||
func errorMessage() -> String {
|
||||
return "Must be at least \(DEFAULT_MIN_LENGTH) characters long"
|
||||
}
|
||||
|
||||
func validate(value: String) -> Bool {
|
||||
if countElements(value) <= DEFAULT_MIN_LENGTH {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
//
|
||||
// MinLengthValidation.swift
|
||||
// Pingo
|
||||
//
|
||||
// Created by Jeff Potter on 11/11/14.
|
||||
// Copyright (c) 2014 Byron Mackay. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
class MinLengthValidation: Validation {
|
||||
let DEFAULT_MIN_LENGTH = 3
|
||||
|
||||
func validate(value: String) -> (Bool, ValidationErrorType) {
|
||||
if countElements(value) < DEFAULT_MIN_LENGTH {
|
||||
return (false, .MinLength)
|
||||
}
|
||||
return (true, .NoError)
|
||||
}
|
||||
}
|
||||
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
class PasswordValidation : Validation {
|
||||
class PasswordRule : Rule {
|
||||
|
||||
// Alternative Regexes
|
||||
|
||||
|
|
@ -19,15 +19,30 @@ class PasswordValidation : Validation {
|
|||
// var PASSWORD_REGEX = "^(?=.*?[A-Z])(?=.*?[0-9])(?=.*?[a-z]).*?$"
|
||||
|
||||
// 8 characters. one uppercase
|
||||
var PASSWORD_REGEX = "^(?=.*?[A-Z]).{8,}$"
|
||||
|
||||
func validate(value: String) -> (Bool, ValidationErrorType) {
|
||||
if let passwordTes = NSPredicate(format: "SELF MATCHES %@", PASSWORD_REGEX) {
|
||||
var REGEX = "^(?=.*?[A-Z]).{8,}$"
|
||||
|
||||
init(){}
|
||||
|
||||
init(regex:String){
|
||||
self.REGEX = regex
|
||||
}
|
||||
|
||||
var message:String {
|
||||
return "Must be 8 characters with 1 uppercase"
|
||||
}
|
||||
|
||||
func validate(value: String) -> Bool {
|
||||
if let passwordTes = NSPredicate(format: "SELF MATCHES %@", REGEX) {
|
||||
if passwordTes.evaluateWithObject(value) {
|
||||
return (true, .NoError)
|
||||
return true
|
||||
}
|
||||
return (false, .Password)
|
||||
return false
|
||||
}
|
||||
return (false, .Password)
|
||||
return false
|
||||
}
|
||||
|
||||
func errorMessage() -> String {
|
||||
return self.message
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
//
|
||||
// PhoneValidation.swift
|
||||
// Pingo
|
||||
//
|
||||
// Created by Jeff Potter on 11/11/14.
|
||||
// Copyright (c) 2014 Byron Mackay. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
class PhoneNumberRule: Rule {
|
||||
// let PHONE_REGEX = "^\\d{3}-\\d{3}-\\d{4}$"
|
||||
let PHONE_REGEX = "^\\d{10}$"
|
||||
|
||||
var message:String {
|
||||
return "Enter a valid 10 digit phone number"
|
||||
}
|
||||
|
||||
func validate(value: String) -> Bool {
|
||||
if let phoneTest = NSPredicate(format: "SELF MATCHES %@", PHONE_REGEX) {
|
||||
if phoneTest.evaluateWithObject(value) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func errorMessage() -> String {
|
||||
return message
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
//
|
||||
// PhoneValidation.swift
|
||||
// Pingo
|
||||
//
|
||||
// Created by Jeff Potter on 11/11/14.
|
||||
// Copyright (c) 2014 Byron Mackay. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
class PhoneNumberValidation: Validation {
|
||||
let PHONE_REGEX = "^\\d{3}-\\d{3}-\\d{4}$"
|
||||
|
||||
func validate(value: String) -> (Bool, ValidationErrorType) {
|
||||
if let phoneTest = NSPredicate(format: "SELF MATCHES %@", PHONE_REGEX) {
|
||||
if phoneTest.evaluateWithObject(value) {
|
||||
return (true, .NoError)
|
||||
}
|
||||
return (false, .PhoneNumber)
|
||||
}
|
||||
return (false, .PhoneNumber)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
//
|
||||
// Required.swift
|
||||
// pyur-ios
|
||||
//
|
||||
// Created by Jeff Potter on 12/22/14.
|
||||
// Copyright (c) 2014 ringseven. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
|
||||
class RequiredRule: Rule {
|
||||
|
||||
init(){}
|
||||
|
||||
var message: String {
|
||||
return "This field is required"
|
||||
}
|
||||
|
||||
func validate(value:String) -> Bool {
|
||||
if value.isEmpty {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func errorMessage() -> String {
|
||||
return message
|
||||
}
|
||||
}
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
//
|
||||
// RequiredValidation.swift
|
||||
// Pingo
|
||||
//
|
||||
// Created by Jeff Potter on 11/11/14.
|
||||
// Copyright (c) 2014 Byron Mackay. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
class RequiredValidation: Validation {
|
||||
|
||||
func validate(value:String) -> (Bool, ValidationErrorType) {
|
||||
if value.isEmpty {
|
||||
return (false, .Required)
|
||||
}
|
||||
return (true, .NoError)
|
||||
}
|
||||
}
|
||||
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
protocol Validation {
|
||||
func validate(value:String) -> (Bool, ValidationErrorType)
|
||||
}
|
||||
protocol Rule {
|
||||
func validate(value:String) -> Bool
|
||||
func errorMessage() -> String
|
||||
}
|
||||
|
|
@ -11,11 +11,12 @@ import UIKit
|
|||
|
||||
class ValidationError {
|
||||
let textField:UITextField
|
||||
let error:ValidationErrorType
|
||||
var errorLabel:UILabel?
|
||||
let errorMessage:String
|
||||
|
||||
init(textField:UITextField, error:ValidationErrorType){
|
||||
init(textField:UITextField, error:String){
|
||||
self.textField = textField
|
||||
self.error = error
|
||||
self.errorMessage = error
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
//
|
||||
// ValidationErrorType.swift
|
||||
// Pingo
|
||||
//
|
||||
// Created by Jeff Potter on 11/11/14.
|
||||
// Copyright (c) 2014 Byron Mackay. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
enum ValidationErrorType {
|
||||
case Required,
|
||||
Email,
|
||||
Password,
|
||||
MinLength,
|
||||
MaxLength,
|
||||
ZipCode,
|
||||
PhoneNumber,
|
||||
FullName,
|
||||
NoError
|
||||
|
||||
func description() -> String {
|
||||
switch self {
|
||||
case .Required:
|
||||
return "Required field"
|
||||
case .Email:
|
||||
return "Must be a valid email"
|
||||
case .MaxLength:
|
||||
return "This field should be less than"
|
||||
case .ZipCode:
|
||||
return "5 digit zipcode"
|
||||
case .PhoneNumber:
|
||||
return "10 digit phone number"
|
||||
case .Password:
|
||||
return "Must be at least 8 characters"
|
||||
case .FullName:
|
||||
return "Provide a first & last name"
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
//
|
||||
// Validations.swift
|
||||
// Pingo
|
||||
//
|
||||
// Created by Jeff Potter on 11/11/14.
|
||||
// Copyright (c) 2014 Byron Mackay. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
class ValidationFactory {
|
||||
class func validationForRule(rule:ValidationRuleType) -> Validation {
|
||||
switch rule {
|
||||
case .Required:
|
||||
return RequiredValidation()
|
||||
case .Email:
|
||||
return EmailValidation()
|
||||
case .MinLength:
|
||||
return MinLengthValidation()
|
||||
case .MaxLength:
|
||||
return MaxLengthValidation()
|
||||
case .PhoneNumber:
|
||||
return PhoneNumberValidation()
|
||||
case .ZipCode:
|
||||
return ZipCodeValidation()
|
||||
case .FullName:
|
||||
return FullNameValidation()
|
||||
default:
|
||||
return RequiredValidation()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -10,20 +10,21 @@ import Foundation
|
|||
import UIKit
|
||||
|
||||
class ValidationRule {
|
||||
let textField:UITextField
|
||||
var rules:[ValidationRuleType] = []
|
||||
var textField:UITextField
|
||||
var errorLabel:UILabel?
|
||||
var rules:[Rule] = []
|
||||
|
||||
init(textField:UITextField, rules:[ValidationRuleType]){
|
||||
init(textField: UITextField, rules:[Rule], errorLabel:UILabel?){
|
||||
self.textField = textField
|
||||
self.errorLabel = errorLabel
|
||||
self.rules = rules
|
||||
}
|
||||
|
||||
func validateField() -> ValidationError? {
|
||||
for rule in rules {
|
||||
var validation = ValidationFactory.validationForRule(rule)
|
||||
var attempt:(isValid:Bool, error:ValidationErrorType) = validation.validate(textField.text)
|
||||
if !attempt.isValid {
|
||||
return ValidationError(textField: textField, error: attempt.error)
|
||||
var isValid:Bool = rule.validate(textField.text)
|
||||
if !isValid {
|
||||
return ValidationError(textField: self.textField, error: rule.errorMessage())
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
|
|
|||
|
|
@ -1,20 +0,0 @@
|
|||
//
|
||||
// ValidationRuleType.swift
|
||||
// Pingo
|
||||
//
|
||||
// Created by Jeff Potter on 11/11/14.
|
||||
// Copyright (c) 2014 Byron Mackay. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
enum ValidationRuleType {
|
||||
case Required,
|
||||
Email,
|
||||
Password,
|
||||
MinLength,
|
||||
MaxLength,
|
||||
ZipCode,
|
||||
PhoneNumber,
|
||||
FullName
|
||||
}
|
||||
|
|
@ -9,57 +9,52 @@
|
|||
import Foundation
|
||||
import UIKit
|
||||
|
||||
protocol ValidationDelegate {
|
||||
@objc protocol ValidationDelegate {
|
||||
func validationWasSuccessful()
|
||||
func validationFailed(errors:[String:ValidationError])
|
||||
}
|
||||
|
||||
protocol ValidationFieldDelegate {
|
||||
func validationFieldFailed(key:String, error:ValidationError)
|
||||
func validationFieldSuccess(key:String, validField:UITextField)
|
||||
func validationFailed(errors:[UITextField:ValidationError])
|
||||
}
|
||||
|
||||
class Validator {
|
||||
// dictionary to handle complex view hierarchies like dynamic tableview cells
|
||||
var validationRules:[String:ValidationRule] = [:]
|
||||
var validationErrors:[String:ValidationError] = [:]
|
||||
|
||||
var errors:[UITextField:ValidationError] = [:]
|
||||
var validations:[UITextField:ValidationRule] = [:]
|
||||
|
||||
init(){}
|
||||
|
||||
// MARK: Using Keys
|
||||
|
||||
func registerFieldByKey(key:String, textField:UITextField, rules:[ValidationRuleType]) {
|
||||
validationRules[key] = ValidationRule(textField: textField, rules: rules)
|
||||
func registerField(textField:UITextField, rules:[Rule]) {
|
||||
validations[textField] = ValidationRule(textField: textField, rules: rules, errorLabel: nil)
|
||||
}
|
||||
|
||||
func validateFieldByKey(key:String, delegate:ValidationFieldDelegate) {
|
||||
if let currentRule:ValidationRule = validationRules[key] {
|
||||
if var error:ValidationError = currentRule.validateField() {
|
||||
delegate.validationFieldFailed(key, error:error)
|
||||
} else {
|
||||
delegate.validationFieldSuccess(key, validField:currentRule.textField)
|
||||
}
|
||||
}
|
||||
func registerField(textField:UITextField, errorLabel:UILabel, rules:[Rule]) {
|
||||
validations[textField] = ValidationRule(textField: textField, rules:rules, errorLabel:errorLabel)
|
||||
}
|
||||
|
||||
func validateAllKeys(delegate:ValidationDelegate){
|
||||
func validateAll(delegate:ValidationDelegate) {
|
||||
|
||||
for key in validationRules.keys {
|
||||
if let currentRule:ValidationRule = validationRules[key] {
|
||||
for field in validations.keys {
|
||||
if let currentRule:ValidationRule = validations[field] {
|
||||
if var error:ValidationError = currentRule.validateField() {
|
||||
validationErrors[key] = error
|
||||
if (currentRule.errorLabel != nil) {
|
||||
error.errorLabel = currentRule.errorLabel
|
||||
}
|
||||
errors[field] = error
|
||||
} else {
|
||||
validationErrors.removeValueForKey(key)
|
||||
errors.removeValueForKey(field)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if validationErrors.isEmpty {
|
||||
if errors.isEmpty {
|
||||
delegate.validationWasSuccessful()
|
||||
} else {
|
||||
delegate.validationFailed(validationErrors)
|
||||
delegate.validationFailed(errors)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func clearErrors(){
|
||||
self.errors = [:]
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -6,8 +6,10 @@
|
|||
// Copyright (c) 2014 jpotts18. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import UIKit
|
||||
|
||||
|
||||
class ViewController: UIViewController , ValidationDelegate, UITextFieldDelegate {
|
||||
|
||||
// TextFields
|
||||
|
|
@ -15,29 +17,26 @@ class ViewController: UIViewController , ValidationDelegate, UITextFieldDelegate
|
|||
@IBOutlet weak var emailTextField: UITextField!
|
||||
@IBOutlet weak var phoneNumberTextField: UITextField!
|
||||
@IBOutlet weak var zipcodeTextField: UITextField!
|
||||
@IBOutlet weak var emailConfirmTextField: UITextField!
|
||||
|
||||
// Error Labels
|
||||
@IBOutlet weak var fullNameErrorLabel: UILabel!
|
||||
@IBOutlet weak var emailErrorLabel: UILabel!
|
||||
@IBOutlet weak var phoneNumberErrorLabel: UILabel!
|
||||
@IBOutlet weak var zipcodeErrorLabel: UILabel!
|
||||
|
||||
let KEYS = ["Full Name", "Email", "Phone", "ZipCode"]
|
||||
@IBOutlet weak var emailConfirmErrorLabel: UILabel!
|
||||
|
||||
let validator = Validator()
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
fullNameTextField.delegate = self
|
||||
emailTextField.delegate = self
|
||||
phoneNumberTextField.delegate = self
|
||||
zipcodeTextField.delegate = self
|
||||
|
||||
validator.registerFieldByKey(KEYS[0], textField: fullNameTextField, rules: [.Required, .FullName])
|
||||
validator.registerFieldByKey(KEYS[1], textField: emailTextField, rules: [.Required, .Email])
|
||||
validator.registerFieldByKey(KEYS[2], textField: phoneNumberTextField, rules: [.Required, .PhoneNumber])
|
||||
validator.registerFieldByKey(KEYS[3], textField: zipcodeTextField, rules: [.Required, .ZipCode])
|
||||
validator.registerField(fullNameTextField, errorLabel: fullNameErrorLabel , rules: [RequiredRule(), FullNameRule()])
|
||||
validator.registerField(emailTextField, errorLabel: emailErrorLabel, rules: [RequiredRule(), EmailRule()])
|
||||
validator.registerField(emailConfirmTextField, errorLabel: emailConfirmErrorLabel, rules: [RequiredRule(), EmailRule(), ConfirmationRule(confirmField: emailTextField)])
|
||||
validator.registerField(phoneNumberTextField, errorLabel: phoneNumberErrorLabel, rules: [RequiredRule(), MinLengthRule(length: 9)])
|
||||
validator.registerField(zipcodeTextField, errorLabel: zipcodeErrorLabel, rules: [RequiredRule(), ZipCodeRule()])
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -49,17 +48,11 @@ class ViewController: UIViewController , ValidationDelegate, UITextFieldDelegate
|
|||
|
||||
@IBAction func submitTapped(sender: AnyObject) {
|
||||
println("Validating...")
|
||||
validator.validateAllKeys(self)
|
||||
self.clearErrors()
|
||||
validator.validateAll(self)
|
||||
}
|
||||
|
||||
// MARK: Error Styling
|
||||
|
||||
func setError(label:UILabel, error:ValidationError) {
|
||||
label.hidden = false
|
||||
label.text = error.error.description()
|
||||
error.textField.layer.borderColor = UIColor.redColor().CGColor
|
||||
error.textField.layer.borderWidth = 2.0
|
||||
}
|
||||
|
||||
func removeError(label:UILabel, textField:UITextField) {
|
||||
label.hidden = true
|
||||
|
|
@ -75,45 +68,33 @@ class ViewController: UIViewController , ValidationDelegate, UITextFieldDelegate
|
|||
|
||||
// MARK: ValidationDelegate Methods
|
||||
|
||||
func validationFailed(errors: [String : ValidationError]) {
|
||||
|
||||
println("Found \(errors.count) errors")
|
||||
|
||||
if var fullNameError = errors[KEYS[0]] {
|
||||
setError(fullNameErrorLabel, error: fullNameError)
|
||||
} else {
|
||||
removeError(fullNameErrorLabel, textField: fullNameTextField)
|
||||
}
|
||||
|
||||
if var emailNameError = errors[KEYS[1]] {
|
||||
setError(emailErrorLabel, error: emailNameError)
|
||||
} else {
|
||||
removeError(emailErrorLabel, textField: emailTextField)
|
||||
}
|
||||
|
||||
if var phoneError = errors[KEYS[2]] {
|
||||
setError(phoneNumberErrorLabel, error: phoneError)
|
||||
} else {
|
||||
removeError(phoneNumberErrorLabel, textField: phoneNumberTextField)
|
||||
}
|
||||
|
||||
if var zipError = errors[KEYS[3]] {
|
||||
setError(zipcodeErrorLabel, error: zipError)
|
||||
} else {
|
||||
removeError(zipcodeErrorLabel, textField: zipcodeTextField)
|
||||
func validationWasSuccessful() {
|
||||
println("Validation Success!")
|
||||
var alert = UIAlertController(title: "Success", message: "You are validated!", preferredStyle: UIAlertControllerStyle.Alert)
|
||||
var defaultAction = UIAlertAction(title: "OK", style: .Default, handler: nil)
|
||||
alert.addAction(defaultAction)
|
||||
self.presentViewController(alert, animated: true, completion: nil)
|
||||
|
||||
}
|
||||
func validationFailed(errors:[UITextField:ValidationError]) {
|
||||
println("Validation FAILED!")
|
||||
self.setErrors()
|
||||
}
|
||||
|
||||
private func setErrors(){
|
||||
for (field, error) in validator.errors {
|
||||
field.layer.borderColor = UIColor.redColor().CGColor
|
||||
field.layer.borderWidth = 1.0
|
||||
error.errorLabel?.text = error.errorMessage
|
||||
error.errorLabel?.hidden = false
|
||||
}
|
||||
}
|
||||
|
||||
func validationWasSuccessful() {
|
||||
|
||||
println("Everything checks out!")
|
||||
|
||||
removeAllErrors()
|
||||
|
||||
var alert = UIAlertController(title: "Valid!", message: "Everything looks good to me", preferredStyle: UIAlertControllerStyle.Alert)
|
||||
alert.addAction(UIAlertAction(title: "Click", style: UIAlertActionStyle.Default, handler: nil))
|
||||
self.presentViewController(alert, animated: true, completion: nil)
|
||||
|
||||
private func clearErrors(){
|
||||
for (field, error) in validator.errors {
|
||||
field.layer.borderWidth = 0.0
|
||||
error.errorLabel?.hidden = true
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,38 @@
|
|||
//
|
||||
// ZipCodeRule.swift
|
||||
// Validator
|
||||
//
|
||||
// Created by Jeff Potter on 3/6/15.
|
||||
// Copyright (c) 2015 jpotts18. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
class ZipCodeRule: Rule {
|
||||
let REGEX = "\\d{5}"
|
||||
|
||||
|
||||
init(){}
|
||||
init(regex:String){
|
||||
self.REGEX = regex
|
||||
}
|
||||
|
||||
var message: String {
|
||||
return "Enter a valid 5 digit zipcode"
|
||||
}
|
||||
|
||||
func validate(value: String) -> Bool {
|
||||
if let zipTest = NSPredicate(format: "SELF MATCHES %@", REGEX) {
|
||||
if zipTest.evaluateWithObject(value) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func errorMessage() -> String {
|
||||
return message
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
//
|
||||
// ZipCodeValidation.swift
|
||||
// Pingo
|
||||
//
|
||||
// Created by Jeff Potter on 11/11/14.
|
||||
// Copyright (c) 2014 Byron Mackay. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
class ZipCodeValidation: Validation {
|
||||
let ZIP_REGEX = "\\d{5}"
|
||||
|
||||
func validate(value: String) -> (Bool, ValidationErrorType) {
|
||||
if let zipTest = NSPredicate(format: "SELF MATCHES %@", ZIP_REGEX) {
|
||||
if zipTest.evaluateWithObject(value) {
|
||||
return (true, .NoError)
|
||||
}
|
||||
return (false, .ZipCode)
|
||||
}
|
||||
return (false, .ZipCode)
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue