Compare commits

...

25 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
29 changed files with 195 additions and 131 deletions

View File

@ -1,15 +1,24 @@
language: objective-c
osx_image: xcode7.1
osx_image: xcode8
xcode_sdk: iphonesimulator10.0
xcode_project: Validator.xcodeproj
xcode_scheme: Validator
before_install:
- gem install cocoapods -v '0.32.1'
- gem install xcpretty --no-rdoc --no-ri --no-document --quiet
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
- xcodebuild clean build test -project Validator.xcodeproj -scheme Validator -sdk iphonesimulator9.1 -destination "OS=9.1,name=iPhone 6" -enableCodeCoverage YES | xcpretty
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
===============
[![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.
@ -22,11 +22,16 @@ platform :ios, "8.1"
use_frameworks!
# As of 4.0.0, SwiftValidator has been extended beyond UITextField
# Swift 3
# Extended beyond UITextField
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'
# For older versions
# Swift 2.1 (limited to UITextField validation)
pod 'SwiftValidator', :git => 'https://github.com/jpotts18/SwiftValidator.git', :tag => '3.0.5'
```
@ -77,7 +82,7 @@ override func viewDidLoad() {
// 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(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
validator.unregisterField(fullNameTextField)
@ -102,16 +107,16 @@ func validationSuccessful() {
// submit the form
}
func validationFailed(errors:[(Validatable ,ValidationError)]) {
// turn the fields to red
for (field, error) in errors {
if let field = field as? UITextField {
field.layer.borderColor = UIColor.redColor().CGColor
field.layer.borderWidth = 1.0
}
error.errorLabel?.text = error.errorMessage // works if you added labels
error.errorLabel?.hidden = false
}
func validationFailed(_ errors:[(Validatable ,ValidationError)]) {
// turn the fields to red
for (field, error) in errors {
if let field = field as? UITextField {
field.layer.borderColor = UIColor.red.cgColor
field.layer.borderWidth = 1.0
}
error.errorLabel?.text = error.errorMessage // works if you added labels
error.errorLabel?.isHidden = false
}
}
```
@ -154,7 +159,7 @@ class SSNVRule: RegexRule {
```
## 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

View File

@ -1,15 +1,15 @@
Pod::Spec.new do |s|
s.name = "SwiftValidator"
s.version = "4.0.0"
s.version = "4.0.2"
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.license = { :type => "MIT", :file => "LICENSE.txt" }
s.author = { "Jeff Potter" => "jeff.potter6@gmail.com" }
s.social_media_url = "http://twitter.com/jpotts18"
s.platform = :ios
s.ios.deployment_target = '8.0'
s.source = { :git => "https://github.com/jpotts18/SwiftValidator.git", :tag => "4.0.0" }
s.source = { :git => "https://github.com/TouchInstinct/SwiftValidator.git", :tag => s.version }
s.source_files = "SwiftValidator/**/*.swift"
s.exclude_files = "Validator/AppDelegate.swift"
s.frameworks = ['Foundation', 'UIKit']

View File

@ -8,7 +8,7 @@
import Foundation
public typealias ValidatableField = protocol<AnyObject, Validatable>
public typealias ValidatableField = AnyObject & Validatable
public protocol Validatable {

View File

@ -23,5 +23,5 @@ public protocol ValidationDelegate {
- returns: No return value.
*/
func validationFailed(errors: [(Validatable, ValidationError)])
func validationFailed(_ errors: [(Validatable, ValidationError)])
}

View File

@ -20,9 +20,9 @@ public class Validator {
/// Dictionary to hold fields by their object identifiers
private var fields = ValidatorDictionary<Validatable>()
/// Variable that holds success closure to display positive status of field.
private var successStyleTransform:((validationRule:ValidationRule)->Void)?
private var successStyleTransform:((_ validationRule:ValidationRule)->Void)?
/// 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.
public init(){}
@ -44,13 +44,13 @@ public class Validator {
// let the user transform the field if they want
if let transform = self.errorStyleTransform {
transform(validationError: error)
transform(error)
}
} else {
// No error
// let the user transform the field if they want
if let transform = self.successStyleTransform {
transform(validationRule: rule)
transform(rule)
}
}
}
@ -65,22 +65,22 @@ public class Validator {
- parameter field: Holds validator field data.
- returns: No return value.
*/
public func validateField(field: ValidatableField, callback: (error:ValidationError?) -> Void){
public func validateField(_ field: ValidatableField, callback: (_ error:ValidationError?) -> Void){
if let fieldRule = validations[field] {
if let error = fieldRule.validateField() {
errors[field] = error
if let transform = self.errorStyleTransform {
transform(validationError: error)
transform(error)
}
callback(error: error)
callback(error)
} else {
if let transform = self.successStyleTransform {
transform(validationRule: fieldRule)
transform(fieldRule)
}
callback(error: nil)
callback(nil)
}
} else {
callback(error: nil)
callback(nil)
}
}
@ -93,7 +93,7 @@ public class Validator {
- parameter error: A closure which is called with validationError, an object that holds validation error data
- 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.errorStyleTransform = error
}
@ -106,7 +106,7 @@ public class Validator {
- parameter rules: A Rule array that holds different rules that apply to said field.
- returns: No return value
*/
public func registerField(field: ValidatableField, errorLabel:UILabel? = nil, rules:[Rule]) {
public func registerField(_ field: ValidatableField, errorLabel:UILabel? = nil, rules:[Rule]) {
validations[field] = ValidationRule(field: field, rules:rules, errorLabel:errorLabel)
fields[field] = field
}
@ -117,7 +117,7 @@ public class Validator {
- parameter field: field used to locate and remove field from validator.
- returns: No return value
*/
public func unregisterField(field:ValidatableField) {
public func unregisterField(_ field:ValidatableField) {
validations.removeValueForKey(field)
errors.removeValueForKey(field)
}
@ -127,7 +127,7 @@ public class Validator {
- returns: No return value.
*/
public func validate(delegate:ValidationDelegate) {
public func validate(_ delegate:ValidationDelegate) {
self.validateAllFields()
@ -145,10 +145,10 @@ public class Validator {
- parameter callback: A closure which is called with errors, a dictionary of type Validatable:ValidationError.
- returns: No return value.
*/
public func validate(callback:(errors:[(Validatable, ValidationError)])->Void) -> Void {
public func validate(_ callback:(_ errors:[(Validatable, ValidationError)])->Void) -> Void {
self.validateAllFields()
callback(errors: errors.map { (fields[$1.field]!, $1) } )
callback(errors.map { (fields[$1.field]!, $1) } )
}
}

View File

@ -8,7 +8,7 @@
import Foundation
public struct ValidatorDictionary<T> : SequenceType {
public struct ValidatorDictionary<T> : Sequence {
private var innerDictionary: [ObjectIdentifier: T] = [:];
@ -31,15 +31,15 @@ public struct ValidatorDictionary<T> : SequenceType {
innerDictionary.removeAll()
}
public mutating func removeValueForKey(key: ValidatableField) {
innerDictionary.removeValueForKey(ObjectIdentifier(key))
public mutating func removeValueForKey(_ key: ValidatableField) {
innerDictionary.removeValue(forKey: ObjectIdentifier(key))
}
public var isEmpty: Bool {
return innerDictionary.isEmpty
}
public func generate() -> DictionaryGenerator<ObjectIdentifier ,T> {
return innerDictionary.generate()
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.
*/
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.
*/
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 {
/// NSCharacter that hold set of valid characters to hold
private let characterSet: NSCharacterSet
private let characterSet: CharacterSet
/// String that holds error message
private var message: String
@ -24,7 +24,7 @@ public class CharacterSetRule: Rule {
- parameter message: String of error message.
- returns: An initialized object, or nil if an object could not be created for some reason that would not result in an exception.
*/
public init(characterSet: NSCharacterSet, message: String = "Enter valid alpha") {
public init(characterSet: CharacterSet, message: String = "Enter valid alpha") {
self.characterSet = characterSet
self.message = message
}
@ -35,9 +35,9 @@ public class CharacterSetRule: Rule {
- parameter value: String to checked for validation.
- 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 {
if !characterSet.longCharacterIsMember(uni.value) {
guard let uniVal = UnicodeScalar(uni.value), characterSet.contains(uniVal) else {
return false
}
}
@ -52,4 +52,4 @@ public class CharacterSetRule: Rule {
public func errorMessage() -> String {
return message
}
}
}

View File

@ -37,7 +37,7 @@ public class ConfirmationRule: Rule {
- parameter value: String to checked for validation.
- returns: A boolean value. True if validation is successful; False if validation fails.
*/
public func validate(value: String) -> Bool {
public func validate(_ value: String) -> Bool {
return confirmField.validationText == value
}
@ -49,4 +49,4 @@ public class ConfirmationRule: Rule {
public func errorMessage() -> String {
return message
}
}
}

View File

@ -26,7 +26,7 @@ public class ExactLengthRule : Rule {
*/
public init(length: Int, message : String = "Must be exactly %ld characters long"){
self.length = length
self.message = NSString(format: message, self.length) as String
self.message = String(format: message, self.length)
}
/**
@ -35,8 +35,8 @@ public class ExactLengthRule : Rule {
- parameter value: String to checked for validation.
- returns: A boolean value. True if validation is successful; False if validation fails.
*/
public func validate(value: String) -> Bool {
return value.characters.count == length
public func validate(_ value: String) -> Bool {
return value.count == length
}
/**
@ -47,4 +47,4 @@ public class ExactLengthRule : Rule {
public func errorMessage() -> String {
return message
}
}
}

View File

@ -31,10 +31,10 @@ public class FloatRule:Rule {
- parameter value: String to checked for validation.
- 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: [])
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 false

View File

@ -30,8 +30,8 @@ public class FullNameRule : Rule {
- parameter value: String to checked for validation.
- returns: A boolean value. True if validation is successful; False if validation fails.
*/
public func validate(value: String) -> Bool {
let nameArray: [String] = value.characters.split { $0 == " " }.map { String($0) }
public func validate(_ value: String) -> Bool {
let nameArray: [String] = value.split { $0 == " " }.map { String($0) }
return nameArray.count >= 2
}
@ -43,4 +43,4 @@ public class FullNameRule : Rule {
public func errorMessage() -> String {
return message
}
}
}

View File

@ -32,13 +32,13 @@ public class ISBNRule: Rule {
- parameter value: String to checked for validation.
- 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 {
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)
}
@ -67,7 +67,7 @@ private protocol ISBNValidator {
- returns: A `Bool` that represents what happened during verification. `false` is returned if
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.
@ -75,7 +75,7 @@ private protocol ISBNValidator {
- returns: A `Bool` that represents the status of the ISBN number. `false` if ISBN number
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
@ -85,7 +85,7 @@ private protocol ISBNValidator {
- returns: A `Bool` that represents the status of the ISBN number. `false` if ISBN number
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
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)
}
@ -112,8 +112,8 @@ extension ISBNValidator {
- returns: A `Bool` that represents the status of the ISBN number. `false` if ISBN number
was not valid, `true` if it was valid.
*/
func checkRegex(input: String) -> Bool {
guard let _ = input.rangeOfString(regex, options: [.RegularExpressionSearch, .AnchoredSearch]) else {
func checkRegex(_ input: String) -> Bool {
guard let _ = input.range(of: regex, options: [.regularExpression, .anchored]) else {
return false
}
@ -136,19 +136,19 @@ private struct ISBN10Validator: ISBNValidator {
- parameter input: String that is checked for ISBN10 validation.
- 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
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
}
}
if (input[input.startIndex.advancedBy(9)] == "X") {
if (input[input.index(input.startIndex, offsetBy: 9)] == "X") {
checksum += 10 * 10
} 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
}
}
@ -171,21 +171,21 @@ private struct ISBN13Validator: ISBNValidator {
- parameter input: String that is checked for ISBN13 validation.
- 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]
var checksum = 0
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)")
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 false
}
}
}

View File

@ -27,7 +27,7 @@ public class MaxLengthRule: Rule {
*/
public init(length: Int, message : String = "Must be at most %ld characters long"){
self.DEFAULT_LENGTH = length
self.message = NSString(format: message, self.DEFAULT_LENGTH) as String
self.message = String(format: message, self.DEFAULT_LENGTH)
}
/**
@ -36,8 +36,8 @@ public class MaxLengthRule: Rule {
- parameter value: String to checked for validation.
- returns: A boolean value. True if validation is successful; False if validation fails.
*/
public func validate(value: String) -> Bool {
return value.characters.count <= DEFAULT_LENGTH
public func validate(_ value: String) -> Bool {
return value.count <= DEFAULT_LENGTH
}
/**

View File

@ -29,7 +29,7 @@ public class MinLengthRule: Rule {
*/
public init(length: Int, message : String = "Must be at least %ld characters long"){
self.DEFAULT_LENGTH = length
self.message = NSString(format: message, self.DEFAULT_LENGTH) as String
self.message = String(format: message, self.DEFAULT_LENGTH)
}
/**
@ -37,8 +37,8 @@ public class MinLengthRule: Rule {
- parameter value: String to checked for validation.
- returns: A boolean value. True if validation is successful; False if validation fails.
*/
public func validate(value: String) -> Bool {
return value.characters.count >= DEFAULT_LENGTH
public func validate(_ value: String) -> Bool {
return value.count >= DEFAULT_LENGTH
}
/**

View File

@ -11,7 +11,7 @@ import Foundation
/**
`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.
private var REGEX: String = "^(?=.*?[A-Z]).{8,}$"
/// String that holds error message.
@ -35,9 +35,9 @@ public class RegexRule : Rule {
- parameter value: String to checked for validation.
- 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)
return test.evaluateWithObject(value)
return test.evaluate(with: value)
}
/**
@ -45,7 +45,7 @@ public class RegexRule : Rule {
- returns: String of error message.
*/
public func errorMessage() -> String {
open func errorMessage() -> String {
return message
}
}

View File

@ -11,7 +11,7 @@ import Foundation
/**
`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.
private var message : String
@ -31,7 +31,7 @@ public class RequiredRule: Rule {
- parameter value: String to checked for validation.
- 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
}
@ -40,7 +40,7 @@ public class RequiredRule: Rule {
- returns: String of error message.
*/
public func errorMessage() -> String {
open func errorMessage() -> String {
return message
}
}
}

View File

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

View File

@ -39,7 +39,7 @@ public class ValidationRule {
*/
public func validateField() -> ValidationError? {
return rules.filter{
return !$0.validate(field.validationText ?? "")
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_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 errorCount = 0
REGISTER_VALIDATOR.styleTransformers(success: { (validationRule) -> Void in
successCount++
successCount+=1
}) { (validationError) -> Void in
errorCount++
errorCount+=1
}
REGISTER_TXT_FIELD.text = INVALID_EMAIL
REGISTER_VALIDATOR.validate { (errors) -> Void in
@ -403,9 +403,9 @@ class SwiftValidatorTests: XCTestCase {
var successCount = 0
var errorCount = 0
REGISTER_VALIDATOR.styleTransformers(success: { (validationRule) -> Void in
successCount++
successCount+=1
}) { (validationError) -> Void in
errorCount++
errorCount+=1
}
REGISTER_TXT_FIELD.text = INVALID_EMAIL
@ -427,7 +427,7 @@ class SwiftValidatorTests: XCTestCase {
REGISTER_TXT_FIELD.text = INVALID_EMAIL
REGISTER_VALIDATOR.validate { (errors) -> Void in
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

@ -396,21 +396,25 @@
attributes = {
LastSwiftMigration = 0700;
LastSwiftUpdateCheck = 0700;
LastUpgradeCheck = 0700;
LastUpgradeCheck = 0930;
ORGANIZATIONNAME = jpotts18;
TargetAttributes = {
62D1AE161A1E6D4400E4DFF8 = {
CreatedOnToolsVersion = 6.1;
LastSwiftMigration = 0800;
};
62D1AE2B1A1E6D4500E4DFF8 = {
CreatedOnToolsVersion = 6.1;
LastSwiftMigration = 0800;
TestTargetID = 62D1AE161A1E6D4400E4DFF8;
};
FB465CB21B9884F400398388 = {
CreatedOnToolsVersion = 6.4;
LastSwiftMigration = 1010;
};
FB465CBC1B9884F400398388 = {
CreatedOnToolsVersion = 6.4;
LastSwiftMigration = 1010;
TestTargetID = 62D1AE161A1E6D4400E4DFF8;
};
};
@ -580,13 +584,23 @@
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = 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_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
@ -595,6 +609,7 @@
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
@ -612,6 +627,7 @@
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 4.0;
};
name = Debug;
};
@ -623,13 +639,23 @@
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = 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_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
@ -637,6 +663,7 @@
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
@ -646,6 +673,8 @@
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_VERSION = 4.0;
VALIDATE_PRODUCT = YES;
};
name = Release;
@ -658,6 +687,7 @@
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "me.jeffpotter.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 4.2;
};
name = Debug;
};
@ -669,6 +699,8 @@
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "me.jeffpotter.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
SWIFT_VERSION = 4.2;
};
name = Release;
};
@ -684,6 +716,7 @@
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "me.jeffpotter.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 4.1;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Validator.app/Validator";
};
name = Debug;
@ -696,6 +729,7 @@
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "me.jeffpotter.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 4.1;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Validator.app/Validator";
};
name = Release;
@ -703,6 +737,7 @@
FB465CCC1B9884F400398388 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_IDENTITY = "";
CURRENT_PROJECT_VERSION = 1;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEFINES_MODULE = YES;
@ -720,6 +755,7 @@
PRODUCT_BUNDLE_IDENTIFIER = "me.jeffpotter.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SWIFT_VERSION = 4.2;
TARGETED_DEVICE_FAMILY = "1,2";
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
@ -729,6 +765,7 @@
FB465CCD1B9884F400398388 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_IDENTITY = "";
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 1;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
@ -743,6 +780,8 @@
PRODUCT_BUNDLE_IDENTIFIER = "me.jeffpotter.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
SWIFT_VERSION = 4.2;
TARGETED_DEVICE_FAMILY = "1,2";
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
@ -767,6 +806,7 @@
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "com.levous.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 4.2;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Validator.app/Validator";
};
name = Debug;
@ -786,6 +826,8 @@
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "com.levous.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
SWIFT_VERSION = 4.2;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Validator.app/Validator";
};
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"?>
<Scheme
LastUpgradeVersion = "0700"
LastUpgradeVersion = "0930"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"

View File

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

View File

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

View File

@ -14,30 +14,30 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
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.
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.
// 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.
// 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.
}
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.
}
func applicationWillTerminate(application: UIApplication) {
func applicationWillTerminate(_ application: UIApplication) {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}

View File

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