diff --git a/.travis.yml b/.travis.yml
index 4c71cce..46ffccd 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,15 +1,24 @@
language: objective-c
-osx_image: xcode7.1
+osx_image: xcode10.1
+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)
\ No newline at end of file
+ - 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
diff --git a/README.md b/README.md
index 59808ba..79e3c7b 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
SwiftValidator
===============
-[](https://travis-ci.org/jpotts18/SwiftValidator) [](https://github.com/Carthage/Carthage) [](https://codecov.io/github/jpotts18/SwiftValidator?branch=master)
+[](https://travis-ci.org/SwiftValidatorCommunity/SwiftValidator) [](https://codecov.io/github/SwiftValidatorCommunity/SwiftValidator?branch=master)
Swift Validator is a rule-based validation library for Swift.
@@ -22,11 +22,19 @@ platform :ios, "8.1"
use_frameworks!
-# As of 4.0.0, SwiftValidator has been extended beyond UITextField
+# Swift 4.2
+pod 'SwiftValidator', :git => 'https://github.com/jpotts18/SwiftValidator.git', :tag => '4.2.0'
+
+# 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 +85,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 +110,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 +162,7 @@ class SSNVRule: RegexRule {
```
## Documentation
-Checkout the docs here via [@jazzydocs](https://twitter.com/jazzydocs).
+Checkout the docs here via [@jazzydocs](https://twitter.com/jazzydocs).
Credits
diff --git a/SwiftValidator.podspec b/SwiftValidator.podspec
index 5a15ee4..e426329 100644
--- a/SwiftValidator.podspec
+++ b/SwiftValidator.podspec
@@ -1,6 +1,7 @@
Pod::Spec.new do |s|
s.name = "SwiftValidator"
s.version = "4.0.0"
+ s.swift_version = "4.2"
s.summary = "A UITextField Validation library for Swift"
s.homepage = "https://github.com/jpotts18/SwiftValidator"
s.screenshots = "https://raw.githubusercontent.com/jpotts18/SwiftValidator/master/swift-validator-v2.gif"
diff --git a/SwiftValidator/Core/Validatable.swift b/SwiftValidator/Core/Validatable.swift
index 6a37253..4778f3a 100644
--- a/SwiftValidator/Core/Validatable.swift
+++ b/SwiftValidator/Core/Validatable.swift
@@ -8,7 +8,7 @@
import Foundation
-public typealias ValidatableField = protocol
+public typealias ValidatableField = AnyObject & Validatable
public protocol Validatable {
@@ -19,7 +19,15 @@ public protocol Validatable {
extension UITextField: Validatable {
+ open var validationText: String {
+ return text ?? ""
+ }
+}
+
+extension UITextView: Validatable {
+
public var validationText: String {
return text ?? ""
}
}
+
diff --git a/SwiftValidator/Core/ValidationDelegate.swift b/SwiftValidator/Core/ValidationDelegate.swift
index edda1ec..0e073ed 100644
--- a/SwiftValidator/Core/ValidationDelegate.swift
+++ b/SwiftValidator/Core/ValidationDelegate.swift
@@ -23,5 +23,5 @@ public protocol ValidationDelegate {
- returns: No return value.
*/
- func validationFailed(errors: [(Validatable, ValidationError)])
+ func validationFailed(_ errors: [(Validatable, ValidationError)])
}
diff --git a/SwiftValidator/Core/Validator.swift b/SwiftValidator/Core/Validator.swift
index 411316f..2553e47 100644
--- a/SwiftValidator/Core/Validator.swift
+++ b/SwiftValidator/Core/Validator.swift
@@ -20,9 +20,9 @@ public class Validator {
/// Dictionary to hold fields by their object identifiers
private var fields = ValidatorDictionary()
/// 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) } )
}
}
diff --git a/SwiftValidator/Core/ValidatorDictionary.swift b/SwiftValidator/Core/ValidatorDictionary.swift
index baab892..e152b0f 100644
--- a/SwiftValidator/Core/ValidatorDictionary.swift
+++ b/SwiftValidator/Core/ValidatorDictionary.swift
@@ -8,7 +8,7 @@
import Foundation
-public struct ValidatorDictionary : SequenceType {
+public struct ValidatorDictionary : Sequence {
private var innerDictionary: [ObjectIdentifier: T] = [:];
@@ -31,15 +31,15 @@ public struct ValidatorDictionary : 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 {
- return innerDictionary.generate()
+ public func makeIterator() -> DictionaryIterator {
+ return innerDictionary.makeIterator()
}
}
diff --git a/SwiftValidator/Rules/AlphaNumericRule.swift b/SwiftValidator/Rules/AlphaNumericRule.swift
index d21dfe8..ba8f017 100644
--- a/SwiftValidator/Rules/AlphaNumericRule.swift
+++ b/SwiftValidator/Rules/AlphaNumericRule.swift
@@ -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)
}
-}
\ No newline at end of file
+}
diff --git a/SwiftValidator/Rules/AlphaRule.swift b/SwiftValidator/Rules/AlphaRule.swift
index 963ea8c..3e9c4cd 100644
--- a/SwiftValidator/Rules/AlphaRule.swift
+++ b/SwiftValidator/Rules/AlphaRule.swift
@@ -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)
}
-}
\ No newline at end of file
+}
diff --git a/SwiftValidator/Rules/CardExpiryMonthRule.swift b/SwiftValidator/Rules/CardExpiryMonthRule.swift
new file mode 100644
index 0000000..3091544
--- /dev/null
+++ b/SwiftValidator/Rules/CardExpiryMonthRule.swift
@@ -0,0 +1,50 @@
+//
+// CardExpiryMonthRule.swift
+// Validator
+//
+// Created by Ifeanyi Ndu on 15/01/2017.
+// Copyright © 2017 jpotts18. All rights reserved.
+//
+
+import Foundation
+
+/**
+ `CardExpiryMonthRule` is a subclass of `Rule` that defines how a credit/debit's card expiry month field is validated
+ */
+public class CardExpiryMonthRule: Rule {
+ /// Error message to be displayed if validation fails.
+ private var message: String = "Must be a valid calendar month"
+ /**
+ Initializes `CardExpiryMonthRule` object with error message. Used to validate a card's expiry month.
+
+ - parameter message: String of error message.
+ - returns: An initialized `CardExpiryMonthRule` object, or nil if an object could not be created for some reason that would not result in an exception.
+ */
+ public init(message : String = "Must be a valid calendar month"){
+ self.message = message
+ }
+
+ /**
+ Validates a field.
+
+ - parameter value: String to check for validation.
+ - returns: Boolean value. True on successful validation, otherwise False on failed Validation.
+ */
+ public func validate(_ value: String) -> Bool {
+
+ guard let month = Int(value) else {
+ return false
+ }
+ return month >= 1 && month <= 12
+ }
+
+ /**
+ Used to display error message when validation fails.
+
+ - returns: String of error message.
+ */
+ public func errorMessage() -> String {
+ return message
+ }
+
+}
diff --git a/SwiftValidator/Rules/CardExpiryYearRule.swift b/SwiftValidator/Rules/CardExpiryYearRule.swift
new file mode 100644
index 0000000..c02eab7
--- /dev/null
+++ b/SwiftValidator/Rules/CardExpiryYearRule.swift
@@ -0,0 +1,59 @@
+//
+// CardExpiryYearRule.swift
+// Validator
+//
+// Created by Ifeanyi Ndu on 15/01/2017.
+// Copyright © 2017 jpotts18. All rights reserved.
+//
+
+import Foundation
+
+/**
+ `CardExpiryYearRule` is a subclass of `Rule` that defines how a credit/debit's card expiry year field is validated
+ */
+public class CardExpiryYearRule: Rule {
+ /// Error message to be displayed if validation fails.
+ private var message: String = "Must be within 3 years of validity"
+ ///Default maximum validity period. Change to preferred value
+ private var MAX_VALIDITY: Int = 3
+
+ /**
+ Initializes `CardExpiryYearRule` object with error message. Used to validate a card's expiry year.
+
+ - parameter message: String of error message.
+ - returns: An initialized `CardExpiryYearRule` object, or nil if an object could not be created for some reason that would not result in an exception.
+ */
+ public init(message : String = "Must be within 3 years of validity"){
+
+ self.message = message
+
+ }
+
+ /**
+ Validates a field.
+
+ - parameter value: String to check for validation.
+ - returns: Boolean value. True on successful validation, otherwise False on failed Validation.
+ */
+ public func validate(_ value: String) -> Bool {
+
+ ///Holds the current year
+ let thisYear = NSCalendar.current.component(Calendar.Component.year, from: Date())
+
+ guard let year = Int(value) else {
+ return false
+ }
+
+ return year >= thisYear && year <= (thisYear + MAX_VALIDITY)
+ }
+
+ /**
+ Used to display error message when validation fails.
+
+ - returns: String of error message.
+ */
+ public func errorMessage() -> String {
+ return message
+ }
+
+}
diff --git a/SwiftValidator/Rules/CharacterSetRule.swift b/SwiftValidator/Rules/CharacterSetRule.swift
index cba73f0..d897132 100644
--- a/SwiftValidator/Rules/CharacterSetRule.swift
+++ b/SwiftValidator/Rules/CharacterSetRule.swift
@@ -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
}
-}
\ No newline at end of file
+}
diff --git a/SwiftValidator/Rules/ConfirmRule.swift b/SwiftValidator/Rules/ConfirmRule.swift
index 0df85f8..52f136d 100644
--- a/SwiftValidator/Rules/ConfirmRule.swift
+++ b/SwiftValidator/Rules/ConfirmRule.swift
@@ -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
}
-}
\ No newline at end of file
+}
diff --git a/SwiftValidator/Rules/ExactLengthRule.swift b/SwiftValidator/Rules/ExactLengthRule.swift
index c19d128..4798bd9 100644
--- a/SwiftValidator/Rules/ExactLengthRule.swift
+++ b/SwiftValidator/Rules/ExactLengthRule.swift
@@ -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
}
-}
\ No newline at end of file
+}
diff --git a/SwiftValidator/Rules/FloatRule.swift b/SwiftValidator/Rules/FloatRule.swift
index 13dea82..669c0e0 100644
--- a/SwiftValidator/Rules/FloatRule.swift
+++ b/SwiftValidator/Rules/FloatRule.swift
@@ -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
diff --git a/SwiftValidator/Rules/FullNameRule.swift b/SwiftValidator/Rules/FullNameRule.swift
index 0d7a5c8..de94c49 100644
--- a/SwiftValidator/Rules/FullNameRule.swift
+++ b/SwiftValidator/Rules/FullNameRule.swift
@@ -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
}
-}
\ No newline at end of file
+}
diff --git a/SwiftValidator/Rules/IPV4Rule.swift b/SwiftValidator/Rules/IPV4Rule.swift
index 5c024bd..3ed7948 100644
--- a/SwiftValidator/Rules/IPV4Rule.swift
+++ b/SwiftValidator/Rules/IPV4Rule.swift
@@ -24,4 +24,4 @@ public class IPV4Rule: RegexRule {
public init(message: String = "Must be a valid IPV4 address") {
super.init(regex: IPV4Rule.regex, message: message)
}
-}
\ No newline at end of file
+}
diff --git a/SwiftValidator/Rules/ISBNRule.swift b/SwiftValidator/Rules/ISBNRule.swift
index a9d724b..4d39b0e 100644
--- a/SwiftValidator/Rules/ISBNRule.swift
+++ b/SwiftValidator/Rules/ISBNRule.swift
@@ -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
}
-}
\ No newline at end of file
+}
diff --git a/SwiftValidator/Rules/MaxLengthRule.swift b/SwiftValidator/Rules/MaxLengthRule.swift
index aea2b2a..0c65d81 100644
--- a/SwiftValidator/Rules/MaxLengthRule.swift
+++ b/SwiftValidator/Rules/MaxLengthRule.swift
@@ -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
}
/**
diff --git a/SwiftValidator/Rules/MinLengthRule.swift b/SwiftValidator/Rules/MinLengthRule.swift
index 300c5d3..b83166d 100644
--- a/SwiftValidator/Rules/MinLengthRule.swift
+++ b/SwiftValidator/Rules/MinLengthRule.swift
@@ -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
}
/**
diff --git a/SwiftValidator/Rules/RegexRule.swift b/SwiftValidator/Rules/RegexRule.swift
index 3a4bbfe..fcbc033 100644
--- a/SwiftValidator/Rules/RegexRule.swift
+++ b/SwiftValidator/Rules/RegexRule.swift
@@ -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
}
}
diff --git a/SwiftValidator/Rules/RequiredRule.swift b/SwiftValidator/Rules/RequiredRule.swift
index 519cc06..dc87ce7 100644
--- a/SwiftValidator/Rules/RequiredRule.swift
+++ b/SwiftValidator/Rules/RequiredRule.swift
@@ -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
@@ -28,10 +28,10 @@ public class RequiredRule: Rule {
/**
Validates a field.
- - parameter value: String to checked for validation.
+ - parameter value: String to check 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
}
-}
\ No newline at end of file
+}
diff --git a/SwiftValidator/Rules/Rule.swift b/SwiftValidator/Rules/Rule.swift
index 6d401ea..2f621c9 100644
--- a/SwiftValidator/Rules/Rule.swift
+++ b/SwiftValidator/Rules/Rule.swift
@@ -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.
diff --git a/SwiftValidator/Rules/ValidationRule.swift b/SwiftValidator/Rules/ValidationRule.swift
index 9bf2655..ef8d306 100644
--- a/SwiftValidator/Rules/ValidationRule.swift
+++ b/SwiftValidator/Rules/ValidationRule.swift
@@ -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
}
-}
\ No newline at end of file
+}
diff --git a/SwiftValidator/Rules/ZipCodeRule.swift b/SwiftValidator/Rules/ZipCodeRule.swift
index 49b3872..f418db6 100644
--- a/SwiftValidator/Rules/ZipCodeRule.swift
+++ b/SwiftValidator/Rules/ZipCodeRule.swift
@@ -18,7 +18,7 @@ public class ZipCodeRule: RegexRule {
- parameter message: 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 convenience init(message : String = "Enter a valid 5 digit zipcode"){
- self.init(regex: "\\d{5}", message : message)
+ public convenience init(message : String = "Enter a valid 5 or 9 digit zipcode"){
+ self.init(regex: "\\d{5}(-\\d{4})?", message : message)
}
-}
\ No newline at end of file
+}
diff --git a/SwiftValidatorTests/SwiftValidatorTests.swift b/SwiftValidatorTests/SwiftValidatorTests.swift
index c8a7574..4672e21 100644
--- a/SwiftValidatorTests/SwiftValidatorTests.swift
+++ b/SwiftValidatorTests/SwiftValidatorTests.swift
@@ -31,10 +31,17 @@ class SwiftValidatorTests: XCTestCase {
let VALID_FLOAT = "1234.444"
let INVALID_FLOAT = "1234.44.44"
+ let VALID_CARD_EXPIRY_MONTH = "10"
+ let INVALID_CARD_EXPIRY_MONTH = "13"
+
+ let VALID_CARD_EXPIRY_YEAR = "2018"
+ let INVALID_CARD_EXPIRY_YEAR = "2016"
+
let LEN_3 = "hey"
let LEN_5 = "Howdy"
let LEN_20 = "Paint the cat orange"
+ let REGISTER_TXT_VIEW = UITextView()
let REGISTER_TXT_FIELD = UITextField()
let REGISTER_VALIDATOR = Validator()
let REGISTER_RULES = [Rule]()
@@ -58,6 +65,36 @@ class SwiftValidatorTests: XCTestCase {
super.tearDown()
}
+
+ // MARK: Expiry Month
+
+ func testCardExpiryMonthValid() {
+ XCTAssertTrue(CardExpiryMonthRule().validate(VALID_CARD_EXPIRY_MONTH), "Expiry month Should be valid")
+ }
+
+ func testCardExpiryMonthInvalid() {
+ XCTAssertFalse(CardExpiryMonthRule().validate(INVALID_CARD_EXPIRY_MONTH), "Expiry month Should be invalid")
+ }
+
+ func testCardExpiryMonthmessage() {
+ XCTAssertNotNil(CardExpiryMonthRule().errorMessage())
+ }
+
+ // MARK: Expiry Year
+
+ func testCardExpiryYearValid() {
+ XCTAssertTrue(CardExpiryYearRule().validate(VALID_CARD_EXPIRY_YEAR), "Expiry year Should be valid")
+ }
+
+ func testCardExpiryYearInvalid() {
+ XCTAssertFalse(CardExpiryYearRule().validate(INVALID_CARD_EXPIRY_YEAR), "Expiry year Should be invalid")
+ }
+
+ func testCardExpiryYearmessage() {
+ XCTAssertNotNil(CardExpiryYearRule().errorMessage())
+ }
+
+
// MARK: Required
func testRequired() {
@@ -320,13 +357,17 @@ class SwiftValidatorTests: XCTestCase {
}
// MARK: Register Field
-
- func testRegisterField(){
+ func testRegisterTextView(){
+ REGISTER_VALIDATOR.registerField(REGISTER_TXT_VIEW, rules: REGISTER_RULES)
+ XCTAssert(REGISTER_VALIDATOR.validations[REGISTER_TXT_VIEW] != nil, "Textfield should register")
+ }
+
+ func testRegisterTextField(){
REGISTER_VALIDATOR.registerField(REGISTER_TXT_FIELD, rules: REGISTER_RULES)
XCTAssert(REGISTER_VALIDATOR.validations[REGISTER_TXT_FIELD] != nil, "Textfield should register")
}
- func testUnregisterField(){
+ func testUnregisterTextField(){
UNREGISTER_VALIDATOR.registerField(UNREGISTER_TXT_FIELD, rules: UNREGISTER_RULES)
UNREGISTER_VALIDATOR.unregisterField(UNREGISTER_TXT_FIELD)
XCTAssert(UNREGISTER_VALIDATOR.validations[UNREGISTER_TXT_FIELD] == nil, "Textfield should unregister")
@@ -366,7 +407,19 @@ 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.characters.count ?? 0 > 0, "Should state 'invalid email'")
+ }
+ }
+
+ func testValidateTextViewField() {
+ REGISTER_VALIDATOR.registerField(REGISTER_TXT_VIEW, rules: [RequiredRule()])
+ REGISTER_TXT_VIEW.text = "Some notes"
+ REGISTER_VALIDATOR.validateField(REGISTER_TXT_VIEW) { error in
+ XCTAssert(error == nil, "Should not present error")
+ }
+ REGISTER_TXT_VIEW.text = nil
+ REGISTER_VALIDATOR.validateField(REGISTER_TXT_VIEW) { error in
+ XCTAssert(error!.errorMessage == "This field is required")
}
}
@@ -385,9 +438,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 +456,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 +480,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")
}
}
}
diff --git a/Validator.xcodeproj/project.pbxproj b/Validator.xcodeproj/project.pbxproj
index 8a746c7..b160122 100644
--- a/Validator.xcodeproj/project.pbxproj
+++ b/Validator.xcodeproj/project.pbxproj
@@ -8,10 +8,6 @@
/* Begin PBXBuildFile section */
62C1821D1C6312F5003788E7 /* ExactLengthRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62C1821C1C6312F5003788E7 /* ExactLengthRule.swift */; };
- 62D1AE1D1A1E6D4400E4DFF8 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62D1AE1C1A1E6D4400E4DFF8 /* AppDelegate.swift */; };
- 62D1AE221A1E6D4400E4DFF8 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 62D1AE201A1E6D4400E4DFF8 /* Main.storyboard */; };
- 62D1AE241A1E6D4400E4DFF8 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 62D1AE231A1E6D4400E4DFF8 /* Images.xcassets */; };
- 62D1AE271A1E6D4400E4DFF8 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 62D1AE251A1E6D4400E4DFF8 /* LaunchScreen.xib */; };
62D9B2561C7C0B2A00BAFCE3 /* ValidationDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62D9B2551C7C0B2A00BAFCE3 /* ValidationDelegate.swift */; };
7CC1E4CF1C636B4500AF013C /* AlphaRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CC1E4CE1C636B4500AF013C /* AlphaRule.swift */; };
7CC1E4D11C637A7700AF013C /* AlphaNumericRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CC1E4D01C637A7700AF013C /* AlphaNumericRule.swift */; };
@@ -19,12 +15,11 @@
7CC1E4D51C637C8500AF013C /* IPV4Rule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CC1E4D41C637C8500AF013C /* IPV4Rule.swift */; };
7CC1E4D71C637F6E00AF013C /* ISBNRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CC1E4D61C637F6E00AF013C /* ISBNRule.swift */; };
7CC1E4DB1C63BFA600AF013C /* HexColorRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CC1E4DA1C63BFA600AF013C /* HexColorRule.swift */; };
+ C87F606A1E2B678B00EB8429 /* CardExpiryMonthRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = C87F60691E2B678B00EB8429 /* CardExpiryMonthRule.swift */; };
+ C87F606C1E2B68C900EB8429 /* CardExpiryYearRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = C87F606B1E2B68C900EB8429 /* CardExpiryYearRule.swift */; };
FB465CB81B9884F400398388 /* SwiftValidator.h in Headers */ = {isa = PBXBuildFile; fileRef = FB465CB71B9884F400398388 /* SwiftValidator.h */; settings = {ATTRIBUTES = (Public, ); }; };
FB465CBE1B9884F400398388 /* SwiftValidator.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FB465CB31B9884F400398388 /* SwiftValidator.framework */; };
FB465CC71B9884F400398388 /* SwiftValidatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = FB465CC61B9884F400398388 /* SwiftValidatorTests.swift */; };
- FB465CCA1B9884F400398388 /* SwiftValidator.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FB465CB31B9884F400398388 /* SwiftValidator.framework */; };
- FB465CCB1B9884F400398388 /* SwiftValidator.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = FB465CB31B9884F400398388 /* SwiftValidator.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
- FB465CE11B98854100398388 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62D1AE1E1A1E6D4400E4DFF8 /* ViewController.swift */; };
FB465CF31B9889EA00398388 /* ConfirmRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = FB465CE31B9889EA00398388 /* ConfirmRule.swift */; };
FB465CF41B9889EA00398388 /* EmailRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = FB465CE41B9889EA00398388 /* EmailRule.swift */; };
FB465CF51B9889EA00398388 /* FloatRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = FB465CE51B9889EA00398388 /* FloatRule.swift */; };
@@ -45,13 +40,6 @@
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
- 62D1AE2D1A1E6D4500E4DFF8 /* PBXContainerItemProxy */ = {
- isa = PBXContainerItemProxy;
- containerPortal = 62D1AE0F1A1E6D4400E4DFF8 /* Project object */;
- proxyType = 1;
- remoteGlobalIDString = 62D1AE161A1E6D4400E4DFF8;
- remoteInfo = Validator;
- };
FB465CBF1B9884F400398388 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 62D1AE0F1A1E6D4400E4DFF8 /* Project object */;
@@ -59,39 +47,10 @@
remoteGlobalIDString = FB465CB21B9884F400398388;
remoteInfo = SwiftValidator;
};
- FB465CC11B9884F400398388 /* PBXContainerItemProxy */ = {
- isa = PBXContainerItemProxy;
- containerPortal = 62D1AE0F1A1E6D4400E4DFF8 /* Project object */;
- proxyType = 1;
- remoteGlobalIDString = 62D1AE161A1E6D4400E4DFF8;
- remoteInfo = Validator;
- };
- FB465CC81B9884F400398388 /* PBXContainerItemProxy */ = {
- isa = PBXContainerItemProxy;
- containerPortal = 62D1AE0F1A1E6D4400E4DFF8 /* Project object */;
- proxyType = 1;
- remoteGlobalIDString = FB465CB21B9884F400398388;
- remoteInfo = SwiftValidator;
- };
/* End PBXContainerItemProxy section */
-/* Begin PBXCopyFilesBuildPhase section */
- FB465CD11B9884F400398388 /* Embed Frameworks */ = {
- isa = PBXCopyFilesBuildPhase;
- buildActionMask = 2147483647;
- dstPath = "";
- dstSubfolderSpec = 10;
- files = (
- FB465CCB1B9884F400398388 /* SwiftValidator.framework in Embed Frameworks */,
- );
- name = "Embed Frameworks";
- runOnlyForDeploymentPostprocessing = 0;
- };
-/* End PBXCopyFilesBuildPhase section */
-
/* Begin PBXFileReference section */
62C1821C1C6312F5003788E7 /* ExactLengthRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExactLengthRule.swift; sourceTree = ""; };
- 62D1AE171A1E6D4400E4DFF8 /* Validator.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Validator.app; sourceTree = BUILT_PRODUCTS_DIR; };
62D1AE1B1A1E6D4400E4DFF8 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
62D1AE1C1A1E6D4400E4DFF8 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
62D1AE1E1A1E6D4400E4DFF8 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; };
@@ -107,6 +66,8 @@
7CC1E4D41C637C8500AF013C /* IPV4Rule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IPV4Rule.swift; sourceTree = ""; };
7CC1E4D61C637F6E00AF013C /* ISBNRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ISBNRule.swift; sourceTree = ""; };
7CC1E4DA1C63BFA600AF013C /* HexColorRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HexColorRule.swift; sourceTree = ""; };
+ C87F60691E2B678B00EB8429 /* CardExpiryMonthRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CardExpiryMonthRule.swift; sourceTree = ""; };
+ C87F606B1E2B68C900EB8429 /* CardExpiryYearRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CardExpiryYearRule.swift; sourceTree = ""; };
FB465CB31B9884F400398388 /* SwiftValidator.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SwiftValidator.framework; sourceTree = BUILT_PRODUCTS_DIR; };
FB465CB61B9884F400398388 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
FB465CB71B9884F400398388 /* SwiftValidator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SwiftValidator.h; sourceTree = ""; };
@@ -133,14 +94,6 @@
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
- 62D1AE141A1E6D4400E4DFF8 /* Frameworks */ = {
- isa = PBXFrameworksBuildPhase;
- buildActionMask = 2147483647;
- files = (
- FB465CCA1B9884F400398388 /* SwiftValidator.framework in Frameworks */,
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
62D1AE291A1E6D4500E4DFF8 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
@@ -180,7 +133,6 @@
62D1AE181A1E6D4400E4DFF8 /* Products */ = {
isa = PBXGroup;
children = (
- 62D1AE171A1E6D4400E4DFF8 /* Validator.app */,
62D1AE2C1A1E6D4500E4DFF8 /* ValidatorTests.xctest */,
FB465CB31B9884F400398388 /* SwiftValidator.framework */,
FB465CBD1B9884F400398388 /* SwiftValidatorTests.xctest */,
@@ -265,6 +217,8 @@
isa = PBXGroup;
children = (
7CC1E4CE1C636B4500AF013C /* AlphaRule.swift */,
+ C87F606B1E2B68C900EB8429 /* CardExpiryYearRule.swift */,
+ C87F60691E2B678B00EB8429 /* CardExpiryMonthRule.swift */,
7CC1E4D01C637A7700AF013C /* AlphaNumericRule.swift */,
7CC1E4D21C637ABC00AF013C /* CharacterSetRule.swift */,
7CC1E4D41C637C8500AF013C /* IPV4Rule.swift */,
@@ -314,25 +268,6 @@
/* End PBXHeadersBuildPhase section */
/* Begin PBXNativeTarget section */
- 62D1AE161A1E6D4400E4DFF8 /* Validator */ = {
- isa = PBXNativeTarget;
- buildConfigurationList = 62D1AE361A1E6D4500E4DFF8 /* Build configuration list for PBXNativeTarget "Validator" */;
- buildPhases = (
- 62D1AE131A1E6D4400E4DFF8 /* Sources */,
- 62D1AE141A1E6D4400E4DFF8 /* Frameworks */,
- 62D1AE151A1E6D4400E4DFF8 /* Resources */,
- FB465CD11B9884F400398388 /* Embed Frameworks */,
- );
- buildRules = (
- );
- dependencies = (
- FB465CC91B9884F400398388 /* PBXTargetDependency */,
- );
- name = Validator;
- productName = Validator;
- productReference = 62D1AE171A1E6D4400E4DFF8 /* Validator.app */;
- productType = "com.apple.product-type.application";
- };
62D1AE2B1A1E6D4500E4DFF8 /* ValidatorTests */ = {
isa = PBXNativeTarget;
buildConfigurationList = 62D1AE391A1E6D4500E4DFF8 /* Build configuration list for PBXNativeTarget "ValidatorTests" */;
@@ -344,7 +279,6 @@
buildRules = (
);
dependencies = (
- 62D1AE2E1A1E6D4500E4DFF8 /* PBXTargetDependency */,
);
name = ValidatorTests;
productName = ValidatorTests;
@@ -381,7 +315,6 @@
);
dependencies = (
FB465CC01B9884F400398388 /* PBXTargetDependency */,
- FB465CC21B9884F400398388 /* PBXTargetDependency */,
);
name = SwiftValidatorTests;
productName = SwiftValidatorTests;
@@ -396,28 +329,28 @@
attributes = {
LastSwiftMigration = 0700;
LastSwiftUpdateCheck = 0700;
- LastUpgradeCheck = 0700;
+ LastUpgradeCheck = 0930;
ORGANIZATIONNAME = jpotts18;
TargetAttributes = {
- 62D1AE161A1E6D4400E4DFF8 = {
- CreatedOnToolsVersion = 6.1;
- };
62D1AE2B1A1E6D4500E4DFF8 = {
CreatedOnToolsVersion = 6.1;
+ LastSwiftMigration = 0820;
TestTargetID = 62D1AE161A1E6D4400E4DFF8;
};
FB465CB21B9884F400398388 = {
CreatedOnToolsVersion = 6.4;
+ LastSwiftMigration = 1020;
};
FB465CBC1B9884F400398388 = {
CreatedOnToolsVersion = 6.4;
+ LastSwiftMigration = 1020;
TestTargetID = 62D1AE161A1E6D4400E4DFF8;
};
};
};
buildConfigurationList = 62D1AE121A1E6D4400E4DFF8 /* Build configuration list for PBXProject "Validator" */;
compatibilityVersion = "Xcode 3.2";
- developmentRegion = English;
+ developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
@@ -428,7 +361,6 @@
projectDirPath = "";
projectRoot = "";
targets = (
- 62D1AE161A1E6D4400E4DFF8 /* Validator */,
62D1AE2B1A1E6D4500E4DFF8 /* ValidatorTests */,
FB465CB21B9884F400398388 /* SwiftValidator */,
FB465CBC1B9884F400398388 /* SwiftValidatorTests */,
@@ -437,16 +369,6 @@
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
- 62D1AE151A1E6D4400E4DFF8 /* Resources */ = {
- isa = PBXResourcesBuildPhase;
- buildActionMask = 2147483647;
- files = (
- 62D1AE221A1E6D4400E4DFF8 /* Main.storyboard in Resources */,
- 62D1AE271A1E6D4400E4DFF8 /* LaunchScreen.xib in Resources */,
- 62D1AE241A1E6D4400E4DFF8 /* Images.xcassets in Resources */,
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
62D1AE2A1A1E6D4500E4DFF8 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
@@ -471,15 +393,6 @@
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
- 62D1AE131A1E6D4400E4DFF8 /* Sources */ = {
- isa = PBXSourcesBuildPhase;
- buildActionMask = 2147483647;
- files = (
- FB465CE11B98854100398388 /* ViewController.swift in Sources */,
- 62D1AE1D1A1E6D4400E4DFF8 /* AppDelegate.swift in Sources */,
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
62D1AE281A1E6D4500E4DFF8 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
@@ -501,9 +414,11 @@
FB465CFD1B9889EA00398388 /* Rule.swift in Sources */,
FB465CFA1B9889EA00398388 /* PhoneNumberRule.swift in Sources */,
FB465CF51B9889EA00398388 /* FloatRule.swift in Sources */,
+ C87F606C1E2B68C900EB8429 /* CardExpiryYearRule.swift in Sources */,
7CC1E4DB1C63BFA600AF013C /* HexColorRule.swift in Sources */,
FB465D011B9889EA00398388 /* Validator.swift in Sources */,
FB465CFE1B9889EA00398388 /* ValidationRule.swift in Sources */,
+ C87F606A1E2B678B00EB8429 /* CardExpiryMonthRule.swift in Sources */,
FB465CF31B9889EA00398388 /* ConfirmRule.swift in Sources */,
FB51E5B01CD208B8004DE696 /* Validatable.swift in Sources */,
7CC1E4D51C637C8500AF013C /* IPV4Rule.swift in Sources */,
@@ -530,26 +445,11 @@
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
- 62D1AE2E1A1E6D4500E4DFF8 /* PBXTargetDependency */ = {
- isa = PBXTargetDependency;
- target = 62D1AE161A1E6D4400E4DFF8 /* Validator */;
- targetProxy = 62D1AE2D1A1E6D4500E4DFF8 /* PBXContainerItemProxy */;
- };
FB465CC01B9884F400398388 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = FB465CB21B9884F400398388 /* SwiftValidator */;
targetProxy = FB465CBF1B9884F400398388 /* PBXContainerItemProxy */;
};
- FB465CC21B9884F400398388 /* PBXTargetDependency */ = {
- isa = PBXTargetDependency;
- target = 62D1AE161A1E6D4400E4DFF8 /* Validator */;
- targetProxy = FB465CC11B9884F400398388 /* PBXContainerItemProxy */;
- };
- FB465CC91B9884F400398388 /* PBXTargetDependency */ = {
- isa = PBXTargetDependency;
- target = FB465CB21B9884F400398388 /* SwiftValidator */;
- targetProxy = FB465CC81B9884F400398388 /* PBXContainerItemProxy */;
- };
/* End PBXTargetDependency section */
/* Begin PBXVariantGroup section */
@@ -580,13 +480,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 +505,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 +523,7 @@
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+ SWIFT_VERSION = 4.2;
};
name = Debug;
};
@@ -623,13 +535,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 +559,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,36 +569,17 @@
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
+ SWIFT_COMPILATION_MODE = wholemodule;
+ SWIFT_VERSION = 4.2;
VALIDATE_PRODUCT = YES;
};
name = Release;
};
- 62D1AE371A1E6D4500E4DFF8 /* Debug */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
- INFOPLIST_FILE = Validator/Info.plist;
- LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
- PRODUCT_BUNDLE_IDENTIFIER = "me.jeffpotter.$(PRODUCT_NAME:rfc1034identifier)";
- PRODUCT_NAME = "$(TARGET_NAME)";
- };
- name = Debug;
- };
- 62D1AE381A1E6D4500E4DFF8 /* Release */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
- INFOPLIST_FILE = Validator/Info.plist;
- LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
- PRODUCT_BUNDLE_IDENTIFIER = "me.jeffpotter.$(PRODUCT_NAME:rfc1034identifier)";
- PRODUCT_NAME = "$(TARGET_NAME)";
- };
- name = Release;
- };
62D1AE3A1A1E6D4500E4DFF8 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
+ CLANG_ENABLE_MODULES = YES;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
@@ -692,6 +596,7 @@
isa = XCBuildConfiguration;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
+ CLANG_ENABLE_MODULES = YES;
INFOPLIST_FILE = ValidatorTests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "me.jeffpotter.$(PRODUCT_NAME:rfc1034identifier)";
@@ -703,6 +608,7 @@
FB465CCC1B9884F400398388 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
+ CODE_SIGN_IDENTITY = "";
CURRENT_PROJECT_VERSION = 1;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEFINES_MODULE = YES;
@@ -720,6 +626,7 @@
PRODUCT_BUNDLE_IDENTIFIER = "me.jeffpotter.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
+ SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
@@ -729,6 +636,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 +651,8 @@
PRODUCT_BUNDLE_IDENTIFIER = "me.jeffpotter.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
+ SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
+ SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
@@ -767,6 +677,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 = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Validator.app/Validator";
};
name = Debug;
@@ -786,6 +697,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 = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Validator.app/Validator";
};
name = Release;
@@ -802,15 +715,6 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
- 62D1AE361A1E6D4500E4DFF8 /* Build configuration list for PBXNativeTarget "Validator" */ = {
- isa = XCConfigurationList;
- buildConfigurations = (
- 62D1AE371A1E6D4500E4DFF8 /* Debug */,
- 62D1AE381A1E6D4500E4DFF8 /* Release */,
- );
- defaultConfigurationIsVisible = 0;
- defaultConfigurationName = Release;
- };
62D1AE391A1E6D4500E4DFF8 /* Build configuration list for PBXNativeTarget "ValidatorTests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
diff --git a/Validator.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Validator.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
new file mode 100644
index 0000000..18d9810
--- /dev/null
+++ b/Validator.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
@@ -0,0 +1,8 @@
+
+
+
+
+ IDEDidComputeMac32BitWarning
+
+
+
diff --git a/Validator.xcodeproj/xcshareddata/xcschemes/SwiftValidator.xcscheme b/Validator.xcodeproj/xcshareddata/xcschemes/SwiftValidator.xcscheme
index 9f3a7ff..d6ae464 100644
--- a/Validator.xcodeproj/xcshareddata/xcschemes/SwiftValidator.xcscheme
+++ b/Validator.xcodeproj/xcshareddata/xcschemes/SwiftValidator.xcscheme
@@ -1,6 +1,6 @@
+ codeCoverageEnabled = "YES"
+ shouldUseLaunchSchemeArgsEnv = "YES">
diff --git a/Validator.xcodeproj/xcshareddata/xcschemes/Validator.xcscheme b/Validator.xcodeproj/xcshareddata/xcschemes/Validator.xcscheme
index 0c76059..5da1196 100644
--- a/Validator.xcodeproj/xcshareddata/xcschemes/Validator.xcscheme
+++ b/Validator.xcodeproj/xcshareddata/xcschemes/Validator.xcscheme
@@ -1,6 +1,6 @@
Bool {
- // Override point for customization after application launch.
+ func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
return true
}
-
- 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) {
- // 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) {
- // 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) {
- // 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) {
- // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
- }
-
-
}
diff --git a/Validator/Base.lproj/Main.storyboard b/Validator/Base.lproj/Main.storyboard
index 8efcb7e..35799c5 100644
--- a/Validator/Base.lproj/Main.storyboard
+++ b/Validator/Base.lproj/Main.storyboard
@@ -1,10 +1,14 @@
-
-
+
+
+
+
+
-
+
+
@@ -16,56 +20,62 @@
-
+
-
+
-
+
+
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
+
@@ -224,8 +268,9 @@
-
+
+
@@ -235,18 +280,23 @@
+
+
+
+
+
@@ -255,6 +305,7 @@
+
@@ -266,6 +317,7 @@
+
@@ -286,50 +338,50 @@
-
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
+
+
+
+
+
+
@@ -351,50 +403,50 @@
-
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
+
+
+
+
+
+
@@ -408,6 +460,8 @@
+
+
@@ -416,7 +470,7 @@
-
+
diff --git a/Validator/Images.xcassets/AppIcon.appiconset/Contents.json b/Validator/Images.xcassets/AppIcon.appiconset/Contents.json
index 118c98f..b8236c6 100644
--- a/Validator/Images.xcassets/AppIcon.appiconset/Contents.json
+++ b/Validator/Images.xcassets/AppIcon.appiconset/Contents.json
@@ -1,5 +1,15 @@
{
"images" : [
+ {
+ "idiom" : "iphone",
+ "size" : "20x20",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "20x20",
+ "scale" : "3x"
+ },
{
"idiom" : "iphone",
"size" : "29x29",
diff --git a/Validator/ViewController.swift b/Validator/ViewController.swift
index 263f914..d04244a 100644
--- a/Validator/ViewController.swift
+++ b/Validator/ViewController.swift
@@ -18,6 +18,7 @@ class ViewController: UIViewController , ValidationDelegate, UITextFieldDelegate
@IBOutlet weak var phoneNumberTextField: UITextField!
@IBOutlet weak var zipcodeTextField: UITextField!
@IBOutlet weak var emailConfirmTextField: UITextField!
+ @IBOutlet weak var notesTextView: UITextView!
// Error Labels
@IBOutlet weak var fullNameErrorLabel: UILabel!
@@ -25,30 +26,37 @@ class ViewController: UIViewController , ValidationDelegate, UITextFieldDelegate
@IBOutlet weak var phoneNumberErrorLabel: UILabel!
@IBOutlet weak var zipcodeErrorLabel: UILabel!
@IBOutlet weak var emailConfirmErrorLabel: UILabel!
+ @IBOutlet weak var notesErrorLabel: UILabel!
let validator = Validator()
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
+ } else if let textField = validationRule.field as? UITextView {
+ 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
+ } else if let textField = validationError.field as? UITextView {
+ textField.layer.borderColor = UIColor.red.cgColor
textField.layer.borderWidth = 1.0
}
})
@@ -58,9 +66,10 @@ class ViewController: UIViewController , ValidationDelegate, UITextFieldDelegate
validator.registerField(emailConfirmTextField, errorLabel: emailConfirmErrorLabel, rules: [RequiredRule(), ConfirmationRule(confirmField: emailTextField)])
validator.registerField(phoneNumberTextField, errorLabel: phoneNumberErrorLabel, rules: [RequiredRule(), MinLengthRule(length: 9)])
validator.registerField(zipcodeTextField, errorLabel: zipcodeErrorLabel, rules: [RequiredRule(), ZipCodeRule()])
+ validator.registerField(notesTextView, errorLabel: notesErrorLabel, rules: [RequiredRule()])
}
- @IBAction func submitTapped(sender: AnyObject) {
+ @IBAction func submitTapped(_ sender: AnyObject) {
print("Validating...")
validator.validate(self)
}
@@ -69,23 +78,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 +105,4 @@ class ViewController: UIViewController , ValidationDelegate, UITextFieldDelegate
return true
}
-}
\ No newline at end of file
+}