Compare commits

...

42 Commits

Author SHA1 Message Date
Alexey Gerasimov db272a717a
Merge pull request #1 from TouchInstinct/feature/newVersion
Podspec fixed
2018-12-03 12:26:46 +03:00
scoreyou 8e0168b270 Version changed 2018-12-03 12:26:05 +03:00
scoreyou f94de389e4 Podspec fixed 2018-12-03 11:51:09 +03:00
scoreyou 0190013526 Moved to swift 4.2 2018-11-30 16:46:41 +03:00
Rajat jain c0ee801a2d
Merge pull request #190 from johannespfeiffer/patch-1
Update README.md
2018-08-10 23:48:27 +05:30
Rajat jain ba27b0e501
Merge pull request #205 from syn-deepakbadiger/Swift_4.1
Enabled Swift 4.1
2018-04-23 21:07:58 +05:30
Jeff Potter fb50b97888
Update .travis.yml 2018-04-22 23:30:12 -06:00
Jeff Potter bef1c1802a
Update README.md 2018-04-22 23:20:02 -06:00
Jeff Potter 4d64561b94
Update README.md 2018-04-22 22:35:22 -06:00
Deepak Badiger b3f8d74212 Enabled Swift 4.1 2018-04-19 14:11:24 -04:00
Johannes Pfeiffer 0debc5d7eb Update README.md
Updated installation snippet to swift 4
2017-09-29 19:06:44 +02:00
David Patterson 6cff6cac3e Merge pull request #175 from andriast/master
Update RegexRule + RequiredRule
2017-07-15 19:38:18 -05:00
Jeff Potter bfa3252c45 Merge pull request #184 from wampir1408/patch-1
Update README.md
2017-07-15 15:18:40 -06:00
Asia d89d18b019 Update README.md
Fixed bug with ZipCodeRule (: for the place of =)
2017-06-02 15:35:07 +02:00
Andrey 696c600dc0 Update RegexRule + RequiredRule 2016-12-04 17:39:39 +02:00
David Patterson 2a6c23ad9e Update README.md
Updated README to highlight how to use different versions of SwiftValidator.
2016-10-06 01:02:33 -05:00
David Patterson 43fddfb385 Merge pull request #161 from jpotts18/swift-3
Swift 3
2016-10-06 00:55:20 -05:00
David Patterson 1efab45d38 Merge pull request #157 from davepatterson/swift3
Swift3
2016-10-05 01:07:36 -05:00
David Patterson 2c68d3db95 updated cocoapods to 0.32.1 on travis 2016-10-05 00:41:18 -05:00
ed-mejia 4f6e77c0aa Updated travis file 2016-08-18 11:24:56 +10:00
ed-mejia 55f282fe92 Updated travis file config 2016-08-18 10:43:40 +10:00
ed-mejia 8bf185d820 Updated travis OS and Simulator 2016-08-18 09:34:20 +10:00
ed-mejia 68fdfbdac0 Updated travis osx_image to xcode8 2016-08-18 09:16:16 +10:00
Edinson Mejia 90e141e923 Fixes to support Xcode Beta 6 2016-08-17 23:10:13 +10:00
ed-mejia 8339c8c086 Fixes to support Swift 3 Xcode Beta 4 2016-08-08 17:26:41 +10:00
David Patterson 3dc5b79272 Merge pull request #130 from sonique6784/patch-1
update code example, fix end parenthesis
2016-07-28 23:00:52 -05:00
David Patterson f8b2d242cf Merge pull request #124 from theoziran/master
fix specs to multiple validation #123
2016-06-29 23:13:42 -05:00
sonique6784 fbaf18ac67 update code example, fix end parenthesis
update code example, fix end parenthesis and validate(self) call, delegate is not need here.
2016-06-25 01:38:57 +10:00
Theoziran Lima 62586fe255 fix specs to multiple validation #123 2016-06-08 10:42:39 -03:00
David Patterson 8f224aba83 Merge pull request #122 from dadalar/master
4.0.0 podspec and readme update
2016-06-03 09:13:04 -05:00
Deniz Adalar 5abb05a423 4.0.0 podspec and readme update 2016-06-03 16:42:55 +03:00
David Patterson db6be7b53c Update README.md 2016-05-31 13:23:34 -05:00
David Patterson 6cfc49799b Update README.md
Updated ReadMe to reflect 4.0.0
2016-05-31 12:23:12 -05:00
David Patterson 2f2e183953 Update README.md
Giving credit where its due.
2016-05-28 12:42:01 -05:00
David Patterson 59d1a6398e Merge pull request #111 from dadalar/ValidatableProtocol
Remove UITextField limitations
2016-05-25 17:22:31 -05:00
Deniz Adalar f344bdc370 Merge branch 'OptionalFunctionParameters' into ValidatableProtocol
# Conflicts:
#	SwiftValidator/Core/ValidationError.swift
#	SwiftValidator/Core/Validator.swift
2016-05-25 12:32:33 +03:00
David Patterson ca7ec31141 Merge pull request #116 from racer1988/fixemailissue
fix #115: support for longer domain names from ICANN
2016-05-13 14:02:12 -05:00
David Patterson 9749d9d670 Merge pull request #114 from dadalar/OptionalFunctionParameters
Remove duplicate functions by using default values
2016-05-12 18:52:32 -05:00
Marco Pappalardo a094156445 fix #115: support for longer domain names from ICANN 2016-05-12 10:45:56 +02:00
Deniz Adalar 39530fb7d6 Remove duplicate (unnecessary) functions by using default values for optional parameters 2016-05-12 10:48:21 +03:00
Deniz Adalar 2fabe418ea Refactor dictionary to return field itself instead of ObjectIdentifier 2016-05-04 16:06:13 +03:00
Deniz Adalar 8f116df330 Removed UITextField limitations and switched to Validatable protocol 2016-05-04 13:39:14 +03:00
32 changed files with 366 additions and 233 deletions

View File

@ -1,15 +1,24 @@
language: objective-c language: objective-c
osx_image: xcode7.1 osx_image: xcode8
xcode_sdk: iphonesimulator10.0
xcode_project: Validator.xcodeproj
xcode_scheme: Validator
before_install: before_install:
- gem install cocoapods -v '0.32.1'
- gem install xcpretty --no-rdoc --no-ri --no-document --quiet - gem install xcpretty --no-rdoc --no-ri --no-document --quiet
script: script:
- xcodebuild clean build test -project Validator.xcodeproj -scheme Validator -sdk iphonesimulator -destination "platform=iOS Simulator,OS=10.0,name=iPhone 6" -enableCodeCoverage YES CODE_SIGNING_REQUIRED=NO | xcpretty
- pod lib lint - pod lib lint
- xcodebuild clean build test -project Validator.xcodeproj -scheme Validator -sdk iphonesimulator9.1 -destination "OS=9.1,name=iPhone 6" -enableCodeCoverage YES | xcpretty
after_success: after_success:
- bash <(curl -s https://codecov.io/bash) - bash <(curl -s https://codecov.io/bash)
notifications:
webhooks:
urls:
- https://webhooks.gitter.im/e/4cfa929bd227586305cc
on_success: change # options: [always|never|change] default: always
on_failure: always # options: [always|never|change] default: always

View File

@ -1,7 +1,7 @@
SwiftValidator SwiftValidator
=============== ===============
[![Build Status](https://travis-ci.org/jpotts18/SwiftValidator.svg?branch=travis-ci)](https://travis-ci.org/jpotts18/SwiftValidator) [![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) [![codecov.io](https://codecov.io/github/jpotts18/SwiftValidator/coverage.svg?branch=master)](https://codecov.io/github/jpotts18/SwiftValidator?branch=master) [![Build Status](https://travis-ci.org/SwiftValidatorCommunity/SwiftValidator.svg?branch=master)](https://travis-ci.org/SwiftValidatorCommunity/SwiftValidator) [![codecov.io](https://codecov.io/github/SwiftValidatorCommunity/SwiftValidator/coverage.svg?branch=master)](https://codecov.io/github/SwiftValidatorCommunity/SwiftValidator?branch=master)
Swift Validator is a rule-based validation library for Swift. Swift Validator is a rule-based validation library for Swift.
@ -21,10 +21,18 @@ source 'https://github.com/CocoaPods/Specs.git'
platform :ios, "8.1" platform :ios, "8.1"
use_frameworks! use_frameworks!
# For SwiftValidator tag 3.0.3
pod 'SwiftValidator', '3.0.3' # Swift 3
# Recommended: For the most recent version of SwiftValidator (master branch) # Extended beyond UITextField
pod 'SwiftValidator', :git => 'https://github.com/jpotts18/SwiftValidator.git', :branch => 'master' pod 'SwiftValidator', :git => 'https://github.com/jpotts18/SwiftValidator.git', :branch => 'master'
# Swift 2.1
# Extended beyond UITextField
# Note: Installing 4.x.x will break code from 3.x.x
pod 'SwiftValidator', :git => 'https://github.com/jpotts18/SwiftValidator.git', :tag => '4.0.0'
# Swift 2.1 (limited to UITextField validation)
pod 'SwiftValidator', :git => 'https://github.com/jpotts18/SwiftValidator.git', :tag => '3.0.5'
``` ```
Install into your project: Install into your project:
@ -74,7 +82,7 @@ override func viewDidLoad() {
// You can now pass in regex and length parameters through overloaded contructors // You can now pass in regex and length parameters through overloaded contructors
validator.registerField(phoneNumberTextField, errorLabel: phoneNumberErrorLabel, rules: [RequiredRule(), MinLengthRule(length: 9)]) validator.registerField(phoneNumberTextField, errorLabel: phoneNumberErrorLabel, rules: [RequiredRule(), MinLengthRule(length: 9)])
validator.registerField(zipcodeTextField, errorLabel: zipcodeErrorLabel, rules: [RequiredRule(), ZipCodeRule(regex = "\\d{5}")]) validator.registerField(zipcodeTextField, errorLabel: zipcodeErrorLabel, rules: [RequiredRule(), ZipCodeRule(regex : "\\d{5}")])
// You can unregister a text field if you no longer want to validate it // You can unregister a text field if you no longer want to validate it
validator.unregisterField(fullNameTextField) validator.unregisterField(fullNameTextField)
@ -86,7 +94,7 @@ Validate Fields on button tap or however you would like to trigger it.
```swift ```swift
@IBAction func signupTapped(sender: AnyObject) { @IBAction func signupTapped(sender: AnyObject) {
validator.validate(delegate:self) validator.validate(self)
} }
``` ```
@ -99,14 +107,16 @@ func validationSuccessful() {
// submit the form // submit the form
} }
func validationFailed(errors:[UITextField:ValidationError]) { func validationFailed(_ errors:[(Validatable ,ValidationError)]) {
// turn the fields to red // turn the fields to red
for (field, error) in validator.errors { for (field, error) in errors {
field.layer.borderColor = UIColor.redColor().CGColor if let field = field as? UITextField {
field.layer.borderWidth = 1.0 field.layer.borderColor = UIColor.red.cgColor
error.errorLabel?.text = error.errorMessage // works if you added labels field.layer.borderWidth = 1.0
error.errorLabel?.hidden = false }
} error.errorLabel?.text = error.errorMessage // works if you added labels
error.errorLabel?.isHidden = false
}
} }
``` ```
@ -149,13 +159,14 @@ class SSNVRule: RegexRule {
``` ```
## Documentation ## Documentation
Checkout the docs <a href="http://jpotts18.github.io/SwiftValidator/">here</a> via [@jazzydocs](https://twitter.com/jazzydocs). Checkout the docs <a href="http://swiftvalidatorcommunity.github.io/SwiftValidator/">here</a> via [@jazzydocs](https://twitter.com/jazzydocs).
Credits Credits
------- -------
Swift Validator is written and maintained by Jeff Potter [@jpotts18](http://twitter.com/jpotts18). David Patterson [@dave_tw12](http://twitter.com/dave_tw12) actively works as a collaborator. Swift Validator is written and maintained by Jeff Potter [@jpotts18](http://twitter.com/jpotts18). David Patterson [@dave_tw12](http://twitter.com/dave_tw12) actively works as a collaborator. Special thanks to [Deniz Adalar](https://github.com/dadalar) for
adding validation beyond UITextField.
## Contributing ## Contributing

View File

@ -1,15 +1,15 @@
Pod::Spec.new do |s| Pod::Spec.new do |s|
s.name = "SwiftValidator" s.name = "SwiftValidator"
s.version = "3.0.1" s.version = "4.0.2"
s.summary = "A UITextField Validation library for Swift" s.summary = "A UITextField Validation library for Swift"
s.homepage = "https://github.com/jpotts18/SwiftValidator" s.homepage = "https://github.com/TouchInstinct/SwiftValidator"
s.screenshots = "https://raw.githubusercontent.com/jpotts18/SwiftValidator/master/swift-validator-v2.gif" s.screenshots = "https://raw.githubusercontent.com/jpotts18/SwiftValidator/master/swift-validator-v2.gif"
s.license = { :type => "MIT", :file => "LICENSE.txt" } s.license = { :type => "MIT", :file => "LICENSE.txt" }
s.author = { "Jeff Potter" => "jeff.potter6@gmail.com" } s.author = { "Jeff Potter" => "jeff.potter6@gmail.com" }
s.social_media_url = "http://twitter.com/jpotts18" s.social_media_url = "http://twitter.com/jpotts18"
s.platform = :ios s.platform = :ios
s.ios.deployment_target = '8.0' s.ios.deployment_target = '8.0'
s.source = { :git => "https://github.com/jpotts18/SwiftValidator.git", :tag => "3.0.1" } s.source = { :git => "https://github.com/TouchInstinct/SwiftValidator.git", :tag => s.version }
s.source_files = "SwiftValidator/**/*.swift" s.source_files = "SwiftValidator/**/*.swift"
s.exclude_files = "Validator/AppDelegate.swift" s.exclude_files = "Validator/AppDelegate.swift"
s.frameworks = ['Foundation', 'UIKit'] s.frameworks = ['Foundation', 'UIKit']

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 = 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. 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. This method will be called on delegate object when validation is successful.
@ -23,5 +23,5 @@ import UIKit
- returns: No return value. - returns: No return value.
*/ */
func validationFailed(errors: [UITextField:ValidationError]) func validationFailed(_ errors: [(Validatable, ValidationError)])
} }

View File

@ -7,38 +7,26 @@ import Foundation
import UIKit 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 { public class ValidationError: NSObject {
/// the textField of the field /// the Validatable field of the field
public let textField:UITextField public let field:ValidatableField
/// the error label of the field /// the error label of the field
public var errorLabel:UILabel? public var errorLabel:UILabel?
/// the error message of the field /// the error message of the field
public let errorMessage:String public let errorMessage:String
/** /**
Initializes `ValidationError` object with a textField and error. Initializes `ValidationError` object with a field, errorLabel, and errorMessage.
- 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
self.errorMessage = error
}
/**
Initializes `ValidationError` object with a textField, errorLabel, and errorMessage.
- parameter textField: UITextField that holds textField.
- parameter errorLabel: UILabel that holds error label. - parameter errorLabel: UILabel that holds error label.
- parameter errorMessage: String that holds error message. - 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. - 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){ public init(field:ValidatableField, errorLabel:UILabel?, error:String){
self.textField = textField self.field = field
self.errorLabel = errorLabel self.errorLabel = errorLabel
self.errorMessage = error self.errorMessage = error
} }

View File

@ -14,13 +14,15 @@ import UIKit
*/ */
public class Validator { public class Validator {
/// Dictionary to hold all fields (and accompanying rules) that will undergo validation. /// Dictionary to hold all fields (and accompanying rules) that will undergo validation.
public var validations = [UITextField:ValidationRule]() public var validations = ValidatorDictionary<ValidationRule>()
/// Dictionary to hold fields (and accompanying errors) that were unsuccessfully validated. /// Dictionary to hold fields (and accompanying errors) that were unsuccessfully validated.
public var errors = [UITextField:ValidationError]() public var errors = ValidatorDictionary<ValidationError>()
/// Variable that holds success closure to display positive status of field. /// Dictionary to hold fields by their object identifiers
private var successStyleTransform:((validationRule:ValidationRule)->Void)? private var fields = ValidatorDictionary<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. /// Variable that holds error closure to display negative status of field.
private var errorStyleTransform:((validationError:ValidationError)->Void)? private var errorStyleTransform:((_ validationError:ValidationError)->Void)?
/// - returns: An initialized object, or nil if an object could not be created for some reason that would not result in an exception. /// - 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(){} public init(){}
@ -34,21 +36,21 @@ public class Validator {
*/ */
private func validateAllFields() { private func validateAllFields() {
errors = [:] errors = ValidatorDictionary<ValidationError>()
for (textField, rule) in validations { for (_, rule) in validations {
if let error = rule.validateField() { if let error = rule.validateField() {
errors[textField] = error errors[rule.field] = error
// let the user transform the field if they want // let the user transform the field if they want
if let transform = self.errorStyleTransform { if let transform = self.errorStyleTransform {
transform(validationError: error) transform(error)
} }
} else { } else {
// No error // No error
// let the user transform the field if they want // let the user transform the field if they want
if let transform = self.successStyleTransform { if let transform = self.successStyleTransform {
transform(validationRule: rule) transform(rule)
} }
} }
} }
@ -60,25 +62,25 @@ public class Validator {
This method is used to validate a single field registered to Validator. If validation is unsuccessful, This method is used to validate a single field registered to Validator. If validation is unsuccessful,
field gets added to errors dictionary. field gets added to errors dictionary.
- parameter textField: Holds validator field data. - parameter field: Holds validator field data.
- returns: No return value. - returns: No return value.
*/ */
public func validateField(textField: UITextField, callback: (error:ValidationError?) -> Void){ public func validateField(_ field: ValidatableField, callback: (_ error:ValidationError?) -> Void){
if let fieldRule = validations[textField] { if let fieldRule = validations[field] {
if let error = fieldRule.validateField() { if let error = fieldRule.validateField() {
errors[textField] = error errors[field] = error
if let transform = self.errorStyleTransform { if let transform = self.errorStyleTransform {
transform(validationError: error) transform(error)
} }
callback(error: error) callback(error)
} else { } else {
if let transform = self.successStyleTransform { if let transform = self.successStyleTransform {
transform(validationRule: fieldRule) transform(fieldRule)
} }
callback(error: nil) callback(nil)
} }
} else { } else {
callback(error: nil) callback(nil)
} }
} }
@ -91,43 +93,33 @@ public class Validator {
- parameter error: A closure which is called with validationError, an object that holds validation error data - parameter error: A closure which is called with validationError, an object that holds validation error data
- returns: No return value - returns: No return value
*/ */
public func styleTransformers(success success:((validationRule:ValidationRule)->Void)?, error:((validationError:ValidationError)->Void)?) { public func styleTransformers(success:((_ validationRule:ValidationRule)->Void)?, error:((_ validationError:ValidationError)->Void)?) {
self.successStyleTransform = success self.successStyleTransform = success
self.errorStyleTransform = error self.errorStyleTransform = error
} }
/** /**
This method is used to add a field to validator. 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 Rule: An array which holds different rules to validate against textField.
- returns: No return value
*/
public func registerField(textField:UITextField, rules:[Rule]) {
validations[textField] = ValidationRule(textField: textField, rules: rules, errorLabel: nil)
}
/**
This method is used to add a field to validator.
- parameter textfield: field that is to be validated.
- parameter errorLabel: A UILabel that holds error label data - 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 - returns: No return value
*/ */
public func registerField(textField:UITextField, errorLabel:UILabel, rules:[Rule]) { public func registerField(_ field: ValidatableField, errorLabel:UILabel? = nil, rules:[Rule]) {
validations[textField] = ValidationRule(textField: textField, rules:rules, errorLabel:errorLabel) validations[field] = ValidationRule(field: field, rules:rules, errorLabel:errorLabel)
fields[field] = field
} }
/** /**
This method is for removing a field validator. 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 - returns: No return value
*/ */
public func unregisterField(textField:UITextField) { public func unregisterField(_ field:ValidatableField) {
validations.removeValueForKey(textField) validations.removeValueForKey(field)
errors.removeValueForKey(textField) errors.removeValueForKey(field)
} }
/** /**
@ -135,14 +127,14 @@ public class Validator {
- returns: No return value. - returns: No return value.
*/ */
public func validate(delegate:ValidationDelegate) { public func validate(_ delegate:ValidationDelegate) {
self.validateAllFields() self.validateAllFields()
if errors.isEmpty { if errors.isEmpty {
delegate.validationSuccessful() delegate.validationSuccessful()
} else { } else {
delegate.validationFailed(errors) delegate.validationFailed(errors.map { (fields[$1.field]!, $1) })
} }
} }
@ -150,13 +142,13 @@ public class Validator {
/** /**
This method validates all fields in validator and sets any errors to errors parameter of callback. 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. - returns: No return value.
*/ */
public func validate(callback:(errors:[UITextField:ValidationError])->Void) -> Void { public func validate(_ callback:(_ errors:[(Validatable, ValidationError)])->Void) -> Void {
self.validateAllFields() self.validateAllFields()
callback(errors: errors) callback(errors.map { (fields[$1.field]!, $1) } )
} }
} }

View File

@ -0,0 +1,45 @@
//
// ValidatorDictionary.swift
// Validator
//
// Created by Deniz Adalar on 04/05/16.
// Copyright © 2016 jpotts18. All rights reserved.
//
import Foundation
public struct ValidatorDictionary<T> : Sequence {
private var innerDictionary: [ObjectIdentifier: T] = [:];
public subscript(key: ValidatableField?) -> T? {
get {
if let key = key {
return innerDictionary[ObjectIdentifier(key)];
} else {
return nil;
}
}
set(newValue) {
if let key = key {
innerDictionary[ObjectIdentifier(key)] = newValue;
}
}
}
public mutating func removeAll() {
innerDictionary.removeAll()
}
public mutating func removeValueForKey(_ key: ValidatableField) {
innerDictionary.removeValue(forKey: ObjectIdentifier(key))
}
public var isEmpty: Bool {
return innerDictionary.isEmpty
}
public func makeIterator() -> DictionaryIterator<ObjectIdentifier ,T> {
return innerDictionary.makeIterator()
}
}

View File

@ -21,6 +21,6 @@ public class AlphaNumericRule: CharacterSetRule {
- returns: An initialized object, or nil if an object could not be created for some reason that would not result in an exception. - 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(message: String = "Enter valid numeric characters") { public init(message: String = "Enter valid numeric characters") {
super.init(characterSet: NSCharacterSet.alphanumericCharacterSet(), message: message) super.init(characterSet: CharacterSet.alphanumerics, message: message)
} }
} }

View File

@ -21,6 +21,6 @@ public class AlphaRule: CharacterSetRule {
- returns: An initialized object, or nil if an object could not be created for some reason. - returns: An initialized object, or nil if an object could not be created for some reason.
*/ */
public init(message: String = "Enter valid alphabetic characters") { public init(message: String = "Enter valid alphabetic characters") {
super.init(characterSet: NSCharacterSet.letterCharacterSet(), message: message) super.init(characterSet: CharacterSet.letters, message: message)
} }
} }

View File

@ -13,7 +13,7 @@ import Foundation
*/ */
public class CharacterSetRule: Rule { public class CharacterSetRule: Rule {
/// NSCharacter that hold set of valid characters to hold /// NSCharacter that hold set of valid characters to hold
private let characterSet: NSCharacterSet private let characterSet: CharacterSet
/// String that holds error message /// String that holds error message
private var message: String private var message: String
@ -24,7 +24,7 @@ public class CharacterSetRule: Rule {
- parameter message: String of error message. - 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. - 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(characterSet: NSCharacterSet, message: String = "Enter valid alpha") { public init(characterSet: CharacterSet, message: String = "Enter valid alpha") {
self.characterSet = characterSet self.characterSet = characterSet
self.message = message self.message = message
} }
@ -35,9 +35,9 @@ public class CharacterSetRule: Rule {
- parameter value: String to checked for validation. - parameter value: String to checked for validation.
- returns: Boolean value. True if validation is successful; False if validation fails. - returns: Boolean value. True if validation is successful; False if validation fails.
*/ */
public func validate(value: String) -> Bool { public func validate(_ value: String) -> Bool {
for uni in value.unicodeScalars { for uni in value.unicodeScalars {
if !characterSet.longCharacterIsMember(uni.value) { guard let uniVal = UnicodeScalar(uni.value), characterSet.contains(uniVal) else {
return false return false
} }
} }
@ -45,11 +45,11 @@ public class CharacterSetRule: Rule {
} }
/** /**
Displays error message when text field fails validation. Displays error message when field fails validation.
- returns: String of error message. - returns: String of error message.
*/ */
public func errorMessage() -> String { public func errorMessage() -> String {
return message return message
} }
} }

View File

@ -10,35 +10,35 @@ import Foundation
import UIKit import UIKit
/** /**
`ConfirmationRule` is a subclass of Rule that defines how a text field that has to be equal `ConfirmationRule` is a subclass of Rule that defines how a field that has to be equal
to another text field is validated. to another field is validated.
*/ */
public class ConfirmationRule: Rule { public class ConfirmationRule: Rule {
/// parameter confirmField: text field to which original text field will be compared to. /// parameter confirmField: field to which original text field will be compared to.
private let confirmField: UITextField private let confirmField: ValidatableField
/// parameter message: String of error message. /// parameter message: String of error message.
private var message : String 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. - 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. - 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.confirmField = confirmField
self.message = message self.message = message
} }
/** /**
Used to validate a text field. Used to validate a field.
- parameter value: String to checked for validation. - parameter value: String to checked for validation.
- returns: A boolean value. True if validation is successful; False if validation fails. - returns: A boolean value. True if validation is successful; False if validation fails.
*/ */
public func validate(value: String) -> Bool { public func validate(_ value: String) -> Bool {
return confirmField.text == value return confirmField.validationText == value
} }
/** /**
@ -49,4 +49,4 @@ public class ConfirmationRule: Rule {
public func errorMessage() -> String { public func errorMessage() -> String {
return message return message
} }
} }

View File

@ -13,10 +13,10 @@ import Foundation
public class EmailRule: RegexRule { public class EmailRule: RegexRule {
/// Regular express string to be used in validation. /// Regular express string to be used in validation.
static let regex = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,6}" static let regex = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}"
/** /**
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. - 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. - 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 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 { public class ExactLengthRule : Rule {
/// parameter message: String of error message. /// parameter message: String of error message.
@ -18,7 +18,7 @@ public class ExactLengthRule : Rule {
private var length : Int 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 length: Integer value of exact string length being specified.
- parameter message: String of error message. - parameter message: String of error message.
@ -26,25 +26,25 @@ public class ExactLengthRule : Rule {
*/ */
public init(length: Int, message : String = "Must be exactly %ld characters long"){ public init(length: Int, message : String = "Must be exactly %ld characters long"){
self.length = length self.length = length
self.message = NSString(format: message, self.length) as String self.message = String(format: message, self.length)
} }
/** /**
Used to validate a text field. Used to validate a field.
- parameter value: String to checked for validation. - parameter value: String to checked for validation.
- returns: A boolean value. True if validation is successful; False if validation fails. - returns: A boolean value. True if validation is successful; False if validation fails.
*/ */
public func validate(value: String) -> Bool { public func validate(_ value: String) -> Bool {
return value.characters.count == length return value.count == length
} }
/** /**
Displays error message if a text field fails validation. Displays error message if a field fails validation.
- returns: String of error message. - returns: String of error message.
*/ */
public func errorMessage() -> String { public func errorMessage() -> String {
return message return message
} }
} }

View File

@ -16,7 +16,7 @@ public class FloatRule:Rule {
private var message : String 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. - 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. - returns: An initialized object, or nil if an object could not be created for some reason that would not result in an exception.
@ -26,22 +26,22 @@ public class FloatRule:Rule {
} }
/** /**
Used to validate text field. Used to validate field.
- parameter value: String to checked for validation. - parameter value: String to checked for validation.
- returns: Boolean value. True if validation is successful; False if validation fails. - returns: Boolean value. True if validation is successful; False if validation fails.
*/ */
public func validate(value: String) -> Bool { public func validate(_ value: String) -> Bool {
let regex = try? NSRegularExpression(pattern: "^[-+]?(\\d*[.])?\\d+$", options: []) let regex = try? NSRegularExpression(pattern: "^[-+]?(\\d*[.])?\\d+$", options: [])
if let regex = regex { if let regex = regex {
let match = regex.numberOfMatchesInString(value, options: [], range: NSRange(location: 0, length: value.characters.count)) let match = regex.numberOfMatches(in: value, options: [], range: NSRange(location: 0, length: value.count))
return match == 1 return match == 1
} }
return false return false
} }
/** /**
Displays error message when text field fails validation. Displays error message when field fails validation.
- returns: String of error message. - returns: String of error message.
*/ */

View File

@ -15,7 +15,7 @@ public class FullNameRule : Rule {
private var message : String 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. - 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. - 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,22 +25,22 @@ public class FullNameRule : Rule {
} }
/** /**
Used to validate a text field. Used to validate a field.
- parameter value: String to checked for validation. - parameter value: String to checked for validation.
- returns: A boolean value. True if validation is successful; False if validation fails. - returns: A boolean value. True if validation is successful; False if validation fails.
*/ */
public func validate(value: String) -> Bool { public func validate(_ value: String) -> Bool {
let nameArray: [String] = value.characters.split { $0 == " " }.map { String($0) } let nameArray: [String] = value.split { $0 == " " }.map { String($0) }
return nameArray.count >= 2 return nameArray.count >= 2
} }
/** /**
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. - returns: String of error message.
*/ */
public func errorMessage() -> String { public func errorMessage() -> String {
return message return message
} }
} }

View File

@ -27,24 +27,24 @@ public class ISBNRule: Rule {
} }
/** /**
Method used to validate text field. Method used to validate field.
- parameter value: String to checked for validation. - parameter value: String to checked for validation.
- returns: Boolean value. True if validation is successful; False if validation fails. - returns: Boolean value. True if validation is successful; False if validation fails.
*/ */
public func validate(value: String) -> Bool { public func validate(_ value: String) -> Bool {
guard let regex = try? NSRegularExpression(pattern: "[\\s-]", options: []) else { guard let regex = try? NSRegularExpression(pattern: "[\\s-]", options: []) else {
fatalError("Invalid ISBN sanitizing regex") fatalError("Invalid ISBN sanitizing regex")
} }
let sanitized = regex.stringByReplacingMatchesInString(value, options: [], range: NSMakeRange(0, value.characters.count), withTemplate: "") let sanitized = regex.stringByReplacingMatches(in: value, options: [], range: NSMakeRange(0, value.count), withTemplate: "")
return ISBN10Validator().verify(sanitized) || ISBN13Validator().verify(sanitized) return ISBN10Validator().verify(sanitized) || ISBN13Validator().verify(sanitized)
} }
/** /**
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. - returns: String of error message.
*/ */
@ -67,7 +67,7 @@ private protocol ISBNValidator {
- returns: A `Bool` that represents what happened during verification. `false` is returned if - returns: A `Bool` that represents what happened during verification. `false` is returned if
it fails, `true` is returned if it was a success. it fails, `true` is returned if it was a success.
*/ */
func verify(input: String) -> Bool func verify(_ input: String) -> Bool
/** /**
Method that verifies regular expression is valid. Method that verifies regular expression is valid.
@ -75,7 +75,7 @@ private protocol ISBNValidator {
- returns: A `Bool` that represents the status of the ISBN number. `false` if ISBN number - returns: A `Bool` that represents the status of the ISBN number. `false` if ISBN number
was not valid, `true` if it was valid. was not valid, `true` if it was valid.
*/ */
func checkRegex(input: String) -> Bool func checkRegex(_ input: String) -> Bool
/** /**
Method that verifies `ISBN` being validated is itself valid. It has to be either ISBN10 Method that verifies `ISBN` being validated is itself valid. It has to be either ISBN10
@ -85,7 +85,7 @@ private protocol ISBNValidator {
- returns: A `Bool` that represents the status of the ISBN number. `false` if ISBN number - returns: A `Bool` that represents the status of the ISBN number. `false` if ISBN number
was not valid, `true` if it was valid. was not valid, `true` if it was valid.
*/ */
func verifyChecksum(input: String) -> Bool func verifyChecksum(_ input: String) -> Bool
} }
/** /**
@ -100,7 +100,7 @@ extension ISBNValidator {
- returns: A `Bool` that represents what happened during verification. `false` is returned if - returns: A `Bool` that represents what happened during verification. `false` is returned if
it fails, `true` is returned if it was a success. it fails, `true` is returned if it was a success.
*/ */
func verify(input: String) -> Bool { func verify(_ input: String) -> Bool {
return checkRegex(input) && verifyChecksum(input) return checkRegex(input) && verifyChecksum(input)
} }
@ -112,8 +112,8 @@ extension ISBNValidator {
- returns: A `Bool` that represents the status of the ISBN number. `false` if ISBN number - returns: A `Bool` that represents the status of the ISBN number. `false` if ISBN number
was not valid, `true` if it was valid. was not valid, `true` if it was valid.
*/ */
func checkRegex(input: String) -> Bool { func checkRegex(_ input: String) -> Bool {
guard let _ = input.rangeOfString(regex, options: [.RegularExpressionSearch, .AnchoredSearch]) else { guard let _ = input.range(of: regex, options: [.regularExpression, .anchored]) else {
return false return false
} }
@ -136,19 +136,19 @@ private struct ISBN10Validator: ISBNValidator {
- parameter input: String that is checked for ISBN10 validation. - parameter input: String that is checked for ISBN10 validation.
- returns: `true` if string is a valid ISBN10 and `false` if it is not. - returns: `true` if string is a valid ISBN10 and `false` if it is not.
*/ */
private func verifyChecksum(input: String) -> Bool { fileprivate func verifyChecksum(_ input: String) -> Bool {
var checksum = 0 var checksum = 0
for i in 0..<9 { for i in 0..<9 {
if let intCharacter = Int(String(input[input.startIndex.advancedBy(i)])) { if let intCharacter = Int(String(input[input.index(input.startIndex, offsetBy: i)])) {
checksum += (i + 1) * intCharacter checksum += (i + 1) * intCharacter
} }
} }
if (input[input.startIndex.advancedBy(9)] == "X") { if (input[input.index(input.startIndex, offsetBy: 9)] == "X") {
checksum += 10 * 10 checksum += 10 * 10
} else { } else {
if let intCharacter = Int(String(input[input.startIndex.advancedBy(9)])) { if let intCharacter = Int(String(input[input.index(input.startIndex, offsetBy: 9)])) {
checksum += 10 * intCharacter checksum += 10 * intCharacter
} }
} }
@ -171,21 +171,21 @@ private struct ISBN13Validator: ISBNValidator {
- parameter input: String that is checked for ISBN13 validation. - parameter input: String that is checked for ISBN13 validation.
- returns: `true` if string is a valid ISBN13 and `false` if it is not. - returns: `true` if string is a valid ISBN13 and `false` if it is not.
*/ */
private func verifyChecksum(input: String) -> Bool { fileprivate func verifyChecksum(_ input: String) -> Bool {
let factor = [1, 3] let factor = [1, 3]
var checksum = 0 var checksum = 0
for i in 0..<12 { for i in 0..<12 {
if let intCharacter = Int(String(input[input.startIndex.advancedBy(i)])) { if let intCharacter = Int(String(input[input.index(input.startIndex, offsetBy: i)])) {
print("\(factor[i%2]) * \(intCharacter)") print("\(factor[i%2]) * \(intCharacter)")
checksum += factor[i % 2] * intCharacter checksum += factor[i % 2] * intCharacter
} }
} }
if let lastInt = Int(String(input[input.startIndex.advancedBy(12)])) { if let lastInt = Int(String(input[input.index(input.startIndex, offsetBy: 12)])) {
return (lastInt - ((10 - (checksum % 10)) % 10) == 0) return (lastInt - ((10 - (checksum % 10)) % 10) == 0)
} }
return false return false
} }
} }

View File

@ -19,7 +19,7 @@ public class MaxLengthRule: Rule {
public init(){} 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 length: Maximum character length.
- parameter message: String of error message. - parameter message: String of error message.
@ -27,21 +27,21 @@ public class MaxLengthRule: Rule {
*/ */
public init(length: Int, message : String = "Must be at most %ld characters long"){ public init(length: Int, message : String = "Must be at most %ld characters long"){
self.DEFAULT_LENGTH = length self.DEFAULT_LENGTH = length
self.message = NSString(format: message, self.DEFAULT_LENGTH) as String self.message = String(format: message, self.DEFAULT_LENGTH)
} }
/** /**
Used to validate a text field. Used to validate a field.
- parameter value: String to checked for validation. - parameter value: String to checked for validation.
- returns: A boolean value. True if validation is successful; False if validation fails. - returns: A boolean value. True if validation is successful; False if validation fails.
*/ */
public func validate(value: String) -> Bool { public func validate(_ value: String) -> Bool {
return value.characters.count <= DEFAULT_LENGTH return value.count <= DEFAULT_LENGTH
} }
/** /**
Displays an error message if a text field fails validation. Displays an error message if a field fails validation.
- returns: String of error message. - returns: String of error message.
*/ */

View File

@ -21,7 +21,7 @@ public class MinLengthRule: Rule {
public init(){} 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 length: Minimum character length.
- parameter message: String of error message. - parameter message: String of error message.
@ -29,20 +29,20 @@ public class MinLengthRule: Rule {
*/ */
public init(length: Int, message : String = "Must be at least %ld characters long"){ public init(length: Int, message : String = "Must be at least %ld characters long"){
self.DEFAULT_LENGTH = length self.DEFAULT_LENGTH = length
self.message = NSString(format: message, self.DEFAULT_LENGTH) as String self.message = String(format: message, self.DEFAULT_LENGTH)
} }
/** /**
Validates a text field. Validates a field.
- parameter value: String to checked for validation. - parameter value: String to checked for validation.
- returns: A boolean value. True if validation is successful; False if validation fails. - returns: A boolean value. True if validation is successful; False if validation fails.
*/ */
public func validate(value: String) -> Bool { public func validate(_ value: String) -> Bool {
return value.characters.count >= DEFAULT_LENGTH return value.count >= DEFAULT_LENGTH
} }
/** /**
Displays error message when text field has failed validation. Displays error message when field has failed validation.
- returns: String of error message. - returns: String of error message.
*/ */

View File

@ -24,7 +24,7 @@ public class PasswordRule : RegexRule {
static let regex = "^(?=.*?[A-Z]).{8,}$" 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. - 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. - 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

@ -11,7 +11,7 @@ import Foundation
/** /**
`RegexRule` is a subclass of Rule that defines how a regular expression is validated. `RegexRule` is a subclass of Rule that defines how a regular expression is validated.
*/ */
public class RegexRule : Rule { open class RegexRule : Rule {
/// Regular express string to be used in validation. /// Regular express string to be used in validation.
private var REGEX: String = "^(?=.*?[A-Z]).{8,}$" private var REGEX: String = "^(?=.*?[A-Z]).{8,}$"
/// String that holds error message. /// String that holds error message.
@ -30,22 +30,22 @@ public class RegexRule : Rule {
} }
/** /**
Method used to validate text field. Method used to validate field.
- parameter value: String to checked for validation. - parameter value: String to checked for validation.
- returns: Boolean value. True if validation is successful; False if validation fails. - returns: Boolean value. True if validation is successful; False if validation fails.
*/ */
public func validate(value: String) -> Bool { open func validate(_ value: String) -> Bool {
let test = NSPredicate(format: "SELF MATCHES %@", self.REGEX) let test = NSPredicate(format: "SELF MATCHES %@", self.REGEX)
return test.evaluateWithObject(value) return test.evaluate(with: value)
} }
/** /**
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. - returns: String of error message.
*/ */
public func errorMessage() -> String { open func errorMessage() -> String {
return message return message
} }
} }

View File

@ -9,9 +9,9 @@
import Foundation 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 { open class RequiredRule: Rule {
/// String that holds error message. /// String that holds error message.
private var message : String private var message : String
@ -26,12 +26,12 @@ public class RequiredRule: Rule {
} }
/** /**
Validates a text field. Validates a field.
- parameter value: String to checked for validation. - parameter value: String to checked for validation.
- returns: Boolean value. True if validation is successful; False if validation fails. - returns: Boolean value. True if validation is successful; False if validation fails.
*/ */
public func validate(value: String) -> Bool { open func validate(_ value: String) -> Bool {
return !value.isEmpty return !value.isEmpty
} }
@ -40,7 +40,7 @@ public class RequiredRule: Rule {
- returns: String of error message. - returns: String of error message.
*/ */
public func errorMessage() -> String { open func errorMessage() -> String {
return message return message
} }
} }

View File

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

View File

@ -9,36 +9,37 @@ import Foundation
import UIKit 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 { public class ValidationRule {
/// the text field of the field /// the field of the field
public var textField:UITextField public var field:ValidatableField
/// the errorLabel of the field /// the errorLabel of the field
public var errorLabel:UILabel? public var errorLabel:UILabel?
/// the rules of the field /// the rules of the field
public var rules:[Rule] = [] 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 field: field that holds actual text in field.
- parameter errorLabel: label that holds error label of text field. - parameter errorLabel: label that holds error label of field.
- parameter rules: array of Rule objects, which text field will be validated against. - 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. - 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?){ public init(field: ValidatableField, rules:[Rule], errorLabel:UILabel?){
self.textField = textField self.field = field
self.errorLabel = errorLabel self.errorLabel = errorLabel
self.rules = rules 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. - returns: `ValidationError` object if at least one error is found. Nil is returned if there are no validation errors.
*/ */
public func validateField() -> ValidationError? { public func validateField() -> ValidationError? {
return rules.filter{ !$0.validate(self.textField.text ?? "") } return rules.filter{
.map{ rule -> ValidationError in return ValidationError(textField: self.textField, errorLabel:self.errorLabel, error: rule.errorMessage()) }.first return !$0.validate(field.validationText)
}.map{ rule -> ValidationError in return ValidationError(field: self.field, errorLabel:self.errorLabel, error: rule.errorMessage()) }.first
} }
} }

View File

@ -366,7 +366,7 @@ class SwiftValidatorTests: XCTestCase {
} }
REGISTER_TXT_FIELD.text = INVALID_EMAIL REGISTER_TXT_FIELD.text = INVALID_EMAIL
REGISTER_VALIDATOR.validateField(REGISTER_TXT_FIELD) { error in REGISTER_VALIDATOR.validateField(REGISTER_TXT_FIELD) { error in
XCTAssert(error?.errorMessage.characters.count > 0, "Should state 'invalid email'") XCTAssert(error?.errorMessage.count ?? 0 > 0, "Should state 'invalid email'")
} }
} }
@ -385,9 +385,9 @@ class SwiftValidatorTests: XCTestCase {
var successCount = 0 var successCount = 0
var errorCount = 0 var errorCount = 0
REGISTER_VALIDATOR.styleTransformers(success: { (validationRule) -> Void in REGISTER_VALIDATOR.styleTransformers(success: { (validationRule) -> Void in
successCount++ successCount+=1
}) { (validationError) -> Void in }) { (validationError) -> Void in
errorCount++ errorCount+=1
} }
REGISTER_TXT_FIELD.text = INVALID_EMAIL REGISTER_TXT_FIELD.text = INVALID_EMAIL
REGISTER_VALIDATOR.validate { (errors) -> Void in REGISTER_VALIDATOR.validate { (errors) -> Void in
@ -403,9 +403,9 @@ class SwiftValidatorTests: XCTestCase {
var successCount = 0 var successCount = 0
var errorCount = 0 var errorCount = 0
REGISTER_VALIDATOR.styleTransformers(success: { (validationRule) -> Void in REGISTER_VALIDATOR.styleTransformers(success: { (validationRule) -> Void in
successCount++ successCount+=1
}) { (validationError) -> Void in }) { (validationError) -> Void in
errorCount++ errorCount+=1
} }
REGISTER_TXT_FIELD.text = INVALID_EMAIL REGISTER_TXT_FIELD.text = INVALID_EMAIL
@ -427,7 +427,7 @@ class SwiftValidatorTests: XCTestCase {
REGISTER_TXT_FIELD.text = INVALID_EMAIL REGISTER_TXT_FIELD.text = INVALID_EMAIL
REGISTER_VALIDATOR.validate { (errors) -> Void in REGISTER_VALIDATOR.validate { (errors) -> Void in
XCTAssert(errors.count == 1, "Should come back with errors") XCTAssert(errors.count == 1, "Should come back with errors")
XCTAssert(!CGColorEqualToColor(self.REGISTER_TXT_FIELD.layer.borderColor, UIColor.redColor().CGColor), "Color shouldn't get set at all") XCTAssert(!(self.REGISTER_TXT_FIELD.layer.borderColor! == UIColor.red.cgColor), "Color shouldn't get set at all")
} }
} }
} }

View File

@ -12,7 +12,7 @@
62D1AE221A1E6D4400E4DFF8 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 62D1AE201A1E6D4400E4DFF8 /* Main.storyboard */; }; 62D1AE221A1E6D4400E4DFF8 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 62D1AE201A1E6D4400E4DFF8 /* Main.storyboard */; };
62D1AE241A1E6D4400E4DFF8 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 62D1AE231A1E6D4400E4DFF8 /* Images.xcassets */; }; 62D1AE241A1E6D4400E4DFF8 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 62D1AE231A1E6D4400E4DFF8 /* Images.xcassets */; };
62D1AE271A1E6D4400E4DFF8 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 62D1AE251A1E6D4400E4DFF8 /* LaunchScreen.xib */; }; 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 */; }; 7CC1E4CF1C636B4500AF013C /* AlphaRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CC1E4CE1C636B4500AF013C /* AlphaRule.swift */; };
7CC1E4D11C637A7700AF013C /* AlphaNumericRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CC1E4D01C637A7700AF013C /* AlphaNumericRule.swift */; }; 7CC1E4D11C637A7700AF013C /* AlphaNumericRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CC1E4D01C637A7700AF013C /* AlphaNumericRule.swift */; };
7CC1E4D31C637ABC00AF013C /* CharacterSetRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CC1E4D21C637ABC00AF013C /* CharacterSetRule.swift */; }; 7CC1E4D31C637ABC00AF013C /* CharacterSetRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CC1E4D21C637ABC00AF013C /* CharacterSetRule.swift */; };
@ -40,6 +40,8 @@
FB465CFF1B9889EA00398388 /* ZipCodeRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = FB465CEF1B9889EA00398388 /* ZipCodeRule.swift */; }; FB465CFF1B9889EA00398388 /* ZipCodeRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = FB465CEF1B9889EA00398388 /* ZipCodeRule.swift */; };
FB465D001B9889EA00398388 /* ValidationError.swift in Sources */ = {isa = PBXBuildFile; fileRef = FB465CF11B9889EA00398388 /* ValidationError.swift */; }; FB465D001B9889EA00398388 /* ValidationError.swift in Sources */ = {isa = PBXBuildFile; fileRef = FB465CF11B9889EA00398388 /* ValidationError.swift */; };
FB465D011B9889EA00398388 /* Validator.swift in Sources */ = {isa = PBXBuildFile; fileRef = FB465CF21B9889EA00398388 /* Validator.swift */; }; FB465D011B9889EA00398388 /* Validator.swift in Sources */ = {isa = PBXBuildFile; fileRef = FB465CF21B9889EA00398388 /* Validator.swift */; };
FB51E5B01CD208B8004DE696 /* Validatable.swift in Sources */ = {isa = PBXBuildFile; fileRef = FB51E5AF1CD208B8004DE696 /* Validatable.swift */; };
FBA963631CDA10130071F03E /* ValidatorDictionary.swift in Sources */ = {isa = PBXBuildFile; fileRef = FBA963621CDA10130071F03E /* ValidatorDictionary.swift */; };
/* End PBXBuildFile section */ /* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */ /* Begin PBXContainerItemProxy section */
@ -126,6 +128,8 @@
FB465CEF1B9889EA00398388 /* ZipCodeRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ZipCodeRule.swift; sourceTree = "<group>"; }; 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>"; }; 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>"; }; 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>"; };
FBA963621CDA10130071F03E /* ValidatorDictionary.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ValidatorDictionary.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */ /* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */ /* Begin PBXFrameworksBuildPhase section */
@ -290,6 +294,8 @@
62D9B2551C7C0B2A00BAFCE3 /* ValidationDelegate.swift */, 62D9B2551C7C0B2A00BAFCE3 /* ValidationDelegate.swift */,
FB465CF11B9889EA00398388 /* ValidationError.swift */, FB465CF11B9889EA00398388 /* ValidationError.swift */,
FB465CF21B9889EA00398388 /* Validator.swift */, FB465CF21B9889EA00398388 /* Validator.swift */,
FB51E5AF1CD208B8004DE696 /* Validatable.swift */,
FBA963621CDA10130071F03E /* ValidatorDictionary.swift */,
); );
path = Core; path = Core;
sourceTree = "<group>"; sourceTree = "<group>";
@ -390,21 +396,25 @@
attributes = { attributes = {
LastSwiftMigration = 0700; LastSwiftMigration = 0700;
LastSwiftUpdateCheck = 0700; LastSwiftUpdateCheck = 0700;
LastUpgradeCheck = 0700; LastUpgradeCheck = 0930;
ORGANIZATIONNAME = jpotts18; ORGANIZATIONNAME = jpotts18;
TargetAttributes = { TargetAttributes = {
62D1AE161A1E6D4400E4DFF8 = { 62D1AE161A1E6D4400E4DFF8 = {
CreatedOnToolsVersion = 6.1; CreatedOnToolsVersion = 6.1;
LastSwiftMigration = 0800;
}; };
62D1AE2B1A1E6D4500E4DFF8 = { 62D1AE2B1A1E6D4500E4DFF8 = {
CreatedOnToolsVersion = 6.1; CreatedOnToolsVersion = 6.1;
LastSwiftMigration = 0800;
TestTargetID = 62D1AE161A1E6D4400E4DFF8; TestTargetID = 62D1AE161A1E6D4400E4DFF8;
}; };
FB465CB21B9884F400398388 = { FB465CB21B9884F400398388 = {
CreatedOnToolsVersion = 6.4; CreatedOnToolsVersion = 6.4;
LastSwiftMigration = 1010;
}; };
FB465CBC1B9884F400398388 = { FB465CBC1B9884F400398388 = {
CreatedOnToolsVersion = 6.4; CreatedOnToolsVersion = 6.4;
LastSwiftMigration = 1010;
TestTargetID = 62D1AE161A1E6D4400E4DFF8; TestTargetID = 62D1AE161A1E6D4400E4DFF8;
}; };
}; };
@ -487,6 +497,7 @@
files = ( files = (
FB465CF41B9889EA00398388 /* EmailRule.swift in Sources */, FB465CF41B9889EA00398388 /* EmailRule.swift in Sources */,
FB465CF61B9889EA00398388 /* FullNameRule.swift in Sources */, FB465CF61B9889EA00398388 /* FullNameRule.swift in Sources */,
FBA963631CDA10130071F03E /* ValidatorDictionary.swift in Sources */,
FB465CFF1B9889EA00398388 /* ZipCodeRule.swift in Sources */, FB465CFF1B9889EA00398388 /* ZipCodeRule.swift in Sources */,
FB465CF91B9889EA00398388 /* PasswordRule.swift in Sources */, FB465CF91B9889EA00398388 /* PasswordRule.swift in Sources */,
7CC1E4D11C637A7700AF013C /* AlphaNumericRule.swift in Sources */, 7CC1E4D11C637A7700AF013C /* AlphaNumericRule.swift in Sources */,
@ -498,6 +509,7 @@
FB465D011B9889EA00398388 /* Validator.swift in Sources */, FB465D011B9889EA00398388 /* Validator.swift in Sources */,
FB465CFE1B9889EA00398388 /* ValidationRule.swift in Sources */, FB465CFE1B9889EA00398388 /* ValidationRule.swift in Sources */,
FB465CF31B9889EA00398388 /* ConfirmRule.swift in Sources */, FB465CF31B9889EA00398388 /* ConfirmRule.swift in Sources */,
FB51E5B01CD208B8004DE696 /* Validatable.swift in Sources */,
7CC1E4D51C637C8500AF013C /* IPV4Rule.swift in Sources */, 7CC1E4D51C637C8500AF013C /* IPV4Rule.swift in Sources */,
7CC1E4D71C637F6E00AF013C /* ISBNRule.swift in Sources */, 7CC1E4D71C637F6E00AF013C /* ISBNRule.swift in Sources */,
FB465D001B9889EA00398388 /* ValidationError.swift in Sources */, FB465D001B9889EA00398388 /* ValidationError.swift in Sources */,
@ -572,13 +584,23 @@
CLANG_CXX_LIBRARY = "libc++"; CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES; CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
@ -587,6 +609,7 @@
ENABLE_TESTABILITY = YES; ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99; GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO; GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0; GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = ( GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1", "DEBUG=1",
@ -604,6 +627,7 @@
ONLY_ACTIVE_ARCH = YES; ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos; SDKROOT = iphoneos;
SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 4.0;
}; };
name = Debug; name = Debug;
}; };
@ -615,13 +639,23 @@
CLANG_CXX_LIBRARY = "libc++"; CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES; CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
@ -629,6 +663,7 @@
ENABLE_NS_ASSERTIONS = NO; ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99; GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNDECLARED_SELECTOR = YES;
@ -638,6 +673,8 @@
IPHONEOS_DEPLOYMENT_TARGET = 8.0; IPHONEOS_DEPLOYMENT_TARGET = 8.0;
MTL_ENABLE_DEBUG_INFO = NO; MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos; SDKROOT = iphoneos;
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_VERSION = 4.0;
VALIDATE_PRODUCT = YES; VALIDATE_PRODUCT = YES;
}; };
name = Release; name = Release;
@ -650,6 +687,7 @@
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "me.jeffpotter.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_BUNDLE_IDENTIFIER = "me.jeffpotter.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 4.2;
}; };
name = Debug; name = Debug;
}; };
@ -661,6 +699,8 @@
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "me.jeffpotter.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_BUNDLE_IDENTIFIER = "me.jeffpotter.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
SWIFT_VERSION = 4.2;
}; };
name = Release; name = Release;
}; };
@ -676,6 +716,7 @@
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "me.jeffpotter.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_BUNDLE_IDENTIFIER = "me.jeffpotter.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 4.1;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Validator.app/Validator"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Validator.app/Validator";
}; };
name = Debug; name = Debug;
@ -688,6 +729,7 @@
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "me.jeffpotter.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_BUNDLE_IDENTIFIER = "me.jeffpotter.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 4.1;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Validator.app/Validator"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Validator.app/Validator";
}; };
name = Release; name = Release;
@ -695,6 +737,7 @@
FB465CCC1B9884F400398388 /* Debug */ = { FB465CCC1B9884F400398388 /* Debug */ = {
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
buildSettings = { buildSettings = {
CODE_SIGN_IDENTITY = "";
CURRENT_PROJECT_VERSION = 1; CURRENT_PROJECT_VERSION = 1;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEFINES_MODULE = YES; DEFINES_MODULE = YES;
@ -712,6 +755,7 @@
PRODUCT_BUNDLE_IDENTIFIER = "me.jeffpotter.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_BUNDLE_IDENTIFIER = "me.jeffpotter.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES; SKIP_INSTALL = YES;
SWIFT_VERSION = 4.2;
TARGETED_DEVICE_FAMILY = "1,2"; TARGETED_DEVICE_FAMILY = "1,2";
VERSIONING_SYSTEM = "apple-generic"; VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = ""; VERSION_INFO_PREFIX = "";
@ -721,6 +765,7 @@
FB465CCD1B9884F400398388 /* Release */ = { FB465CCD1B9884F400398388 /* Release */ = {
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
buildSettings = { buildSettings = {
CODE_SIGN_IDENTITY = "";
COPY_PHASE_STRIP = NO; COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 1; CURRENT_PROJECT_VERSION = 1;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
@ -735,6 +780,8 @@
PRODUCT_BUNDLE_IDENTIFIER = "me.jeffpotter.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_BUNDLE_IDENTIFIER = "me.jeffpotter.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES; SKIP_INSTALL = YES;
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
SWIFT_VERSION = 4.2;
TARGETED_DEVICE_FAMILY = "1,2"; TARGETED_DEVICE_FAMILY = "1,2";
VERSIONING_SYSTEM = "apple-generic"; VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = ""; VERSION_INFO_PREFIX = "";
@ -759,6 +806,7 @@
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "com.levous.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_BUNDLE_IDENTIFIER = "com.levous.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 4.2;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Validator.app/Validator"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Validator.app/Validator";
}; };
name = Debug; name = Debug;
@ -778,6 +826,8 @@
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "com.levous.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_BUNDLE_IDENTIFIER = "com.levous.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
SWIFT_VERSION = 4.2;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Validator.app/Validator"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Validator.app/Validator";
}; };
name = Release; name = Release;

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Scheme <Scheme
LastUpgradeVersion = "0700" LastUpgradeVersion = "0930"
version = "1.3"> version = "1.3">
<BuildAction <BuildAction
parallelizeBuildables = "YES" parallelizeBuildables = "YES"

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Scheme <Scheme
LastUpgradeVersion = "0700" LastUpgradeVersion = "0930"
version = "1.3"> version = "1.3">
<BuildAction <BuildAction
parallelizeBuildables = "YES" parallelizeBuildables = "YES"
@ -26,8 +26,8 @@
buildConfiguration = "Debug" buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES" codeCoverageEnabled = "YES"
codeCoverageEnabled = "YES"> shouldUseLaunchSchemeArgsEnv = "YES">
<Testables> <Testables>
<TestableReference <TestableReference
skipped = "NO"> skipped = "NO">

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Scheme <Scheme
LastUpgradeVersion = "0700" LastUpgradeVersion = "0930"
version = "1.3"> version = "1.3">
<BuildAction <BuildAction
parallelizeBuildables = "YES" parallelizeBuildables = "YES"

View File

@ -14,30 +14,30 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow? var window: UIWindow?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch. // Override point for customization after application launch.
return true return true
} }
func applicationWillResignActive(application: UIApplication) { func applicationWillResignActive(_ application: UIApplication) {
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
} }
func applicationDidEnterBackground(application: UIApplication) { func applicationDidEnterBackground(_ application: UIApplication) {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
} }
func applicationWillEnterForeground(application: UIApplication) { func applicationWillEnterForeground(_ application: UIApplication) {
// Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
} }
func applicationDidBecomeActive(application: UIApplication) { func applicationDidBecomeActive(_ application: UIApplication) {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
} }
func applicationWillTerminate(application: UIApplication) { func applicationWillTerminate(_ application: UIApplication) {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
} }

View File

@ -31,22 +31,26 @@ class ViewController: UIViewController , ValidationDelegate, UITextFieldDelegate
override func viewDidLoad() { override func viewDidLoad() {
super.viewDidLoad() super.viewDidLoad()
self.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: "hideKeyboard")) self.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(ViewController.hideKeyboard)))
validator.styleTransformers(success:{ (validationRule) -> Void in validator.styleTransformers(success:{ (validationRule) -> Void in
print("here") print("here")
// clear error label // clear error label
validationRule.errorLabel?.hidden = true validationRule.errorLabel?.isHidden = true
validationRule.errorLabel?.text = "" validationRule.errorLabel?.text = ""
validationRule.textField.layer.borderColor = UIColor.greenColor().CGColor if let textField = validationRule.field as? UITextField {
validationRule.textField.layer.borderWidth = 0.5 textField.layer.borderColor = UIColor.green.cgColor
textField.layer.borderWidth = 0.5
}, error:{ (validationError) -> Void in
print("error") }
validationError.errorLabel?.hidden = false }, error:{ (validationError) -> Void in
validationError.errorLabel?.text = validationError.errorMessage print("error")
validationError.textField.layer.borderColor = UIColor.redColor().CGColor validationError.errorLabel?.isHidden = false
validationError.textField.layer.borderWidth = 1.0 validationError.errorLabel?.text = validationError.errorMessage
if let textField = validationError.field as? UITextField {
textField.layer.borderColor = UIColor.red.cgColor
textField.layer.borderWidth = 1.0
}
}) })
validator.registerField(fullNameTextField, errorLabel: fullNameErrorLabel , rules: [RequiredRule(), FullNameRule()]) validator.registerField(fullNameTextField, errorLabel: fullNameErrorLabel , rules: [RequiredRule(), FullNameRule()])
@ -56,7 +60,7 @@ class ViewController: UIViewController , ValidationDelegate, UITextFieldDelegate
validator.registerField(zipcodeTextField, errorLabel: zipcodeErrorLabel, rules: [RequiredRule(), ZipCodeRule()]) validator.registerField(zipcodeTextField, errorLabel: zipcodeErrorLabel, rules: [RequiredRule(), ZipCodeRule()])
} }
@IBAction func submitTapped(sender: AnyObject) { @IBAction func submitTapped(_ sender: AnyObject) {
print("Validating...") print("Validating...")
validator.validate(self) validator.validate(self)
} }
@ -65,23 +69,23 @@ class ViewController: UIViewController , ValidationDelegate, UITextFieldDelegate
func validationSuccessful() { func validationSuccessful() {
print("Validation Success!") print("Validation Success!")
let alert = UIAlertController(title: "Success", message: "You are validated!", preferredStyle: UIAlertControllerStyle.Alert) let alert = UIAlertController(title: "Success", message: "You are validated!", preferredStyle: UIAlertController.Style.alert)
let defaultAction = UIAlertAction(title: "OK", style: .Default, handler: nil) let defaultAction = UIAlertAction(title: "OK", style: .default, handler: nil)
alert.addAction(defaultAction) alert.addAction(defaultAction)
self.presentViewController(alert, animated: true, completion: nil) self.present(alert, animated: true, completion: nil)
} }
func validationFailed(errors:[UITextField:ValidationError]) { func validationFailed(_ errors:[(Validatable, ValidationError)]) {
print("Validation FAILED!") print("Validation FAILED!")
} }
func hideKeyboard(){ @objc func hideKeyboard(){
self.view.endEditing(true) self.view.endEditing(true)
} }
// MARK: Validate single field // MARK: Validate single field
// Don't forget to use UITextFieldDelegate // Don't forget to use UITextFieldDelegate
func textFieldShouldReturn(textField: UITextField) -> Bool { func textFieldShouldReturn(_ textField: UITextField) -> Bool {
validator.validateField(textField){ error in validator.validateField(textField){ error in
if error == nil { if error == nil {
// Field validation was successful // Field validation was successful
@ -92,4 +96,4 @@ class ViewController: UIViewController , ValidationDelegate, UITextFieldDelegate
return true return true
} }
} }