Skip to content
This repository has been archived by the owner on Jun 11, 2024. It is now read-only.

Commit

Permalink
Feature compatibility with PMValidation 1.3.1
Browse files Browse the repository at this point in the history
• Added ability to add and remove ValidationUnit instances from a ValidationManager instance using the new addUnit() and removeUnitForIdentifier() methods.
• Added enabled boolean property to ValidationUnit, which disables validation when set to NO. ValidationManager will skip units thusly disabled and not count them toward the global validation state.
• Fixed potential retain cycle in ValidationUnit's validateText() method.
  • Loading branch information
poetmountain committed Jan 6, 2015
1 parent b11c150 commit 1f44050
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 32 deletions.
38 changes: 36 additions & 2 deletions Classes/ValidationManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ class ValidationManager {

var validationUnits = [String:ValidationUnit]()
var valid:Bool = false
var identifierCounter = 0


func registerTextField(textField:UITextField, validationTypes:[ValidatorType]=[], identifier:String?) -> ValidationUnit {
Expand All @@ -34,7 +35,8 @@ class ValidationManager {

func registerObject(object:AnyObject, validationTypes:[ValidatorType]=[], objectNotificationType:String, initialText:String, identifier:String?) -> ValidationUnit {

var unit_identifier:String = identifier ?? "\(self.validationUnits.count+1)"
// if no identifier passed in, generate one
let unit_identifier:String = identifier! ?? self.generateIdentifier()

// create validation unit with passed-in types and store a reference
let unit:ValidationUnit = ValidationUnit(validatorTypes: validationTypes, identifier: unit_identifier, initialText: initialText)
Expand All @@ -52,6 +54,31 @@ class ValidationManager {
}


func addUnit(unit:ValidationUnit, identifier:String?) -> String {

// if an identifier is passed in, that is used instead of the unit's identifier property
// if no identifier passed in and no identifier found on the unit, generate one
let unit_identifier:String = (identifier! ?? unit.identifier) ?? self.generateIdentifier()

self.validationUnits[unit_identifier] = unit

// listen for validation updates from unit
NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("unitUpdateNotificationHandler:"), name: ValidationUnitUpdateNotification, object: unit)

return unit_identifier
}


func removeUnitForIdentifier(identifier:String) {

// remove validation update listener for this unit
let unit = self.unitForIdentifier(identifier)
NSNotificationCenter.defaultCenter().removeObserver(self, name: ValidationUnitUpdateNotification, object: unit)

self.validationUnits.removeValueForKey(identifier)
}


func dealloc() {
NSNotificationCenter.defaultCenter().removeObserver(self)
}
Expand All @@ -67,6 +94,13 @@ class ValidationManager {
}


func generateIdentifier() -> String {
let identifier = "\(self.identifierCounter++)"

return identifier
}


func checkValidationForText() {

for (key, unit) in self.validationUnits {
Expand All @@ -80,7 +114,7 @@ class ValidationManager {
var is_valid:Bool = true

for (key, unit) in self.validationUnits {
if (!unit.valid) {
if (unit.enabled && !unit.valid) {
is_valid = false
break
}
Expand Down
3 changes: 3 additions & 0 deletions Classes/ValidationTypes/ValidatorEmailType.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ class ValidatorEmailType:ValidatorType {

self.valid = false

// while Unicode characters are permissible in user and domain sections of an e-mail address, they must be encoded and use IDNA.
// (see: http://en.wikipedia.org/wiki/Unicode_and_e-mail#Unicode_support_in_message_headings )
// this validation does not parse or check thusly-encoded strings for well-formedness (yet?)
if let regex = NSRegularExpression(pattern: "^[+\\w\\.\\-'!#$%&*+-/=?^_`{|}~]+@[a-zA-Z0-9-]+(\\.[a-zA-Z]{2,})+$", options: .CaseInsensitive, error: &error) {

let num_matches:Int = regex.numberOfMatchesInString(text, options: .ReportProgress, range: NSMakeRange(0, text.utf16Count))
Expand Down
68 changes: 39 additions & 29 deletions Classes/ValidationUnit.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ class ValidationUnit {
var errors = [String:[String]]()
var identifier = ""
var valid:Bool = false
var enabled:Bool = true
let validationQueue:dispatch_queue_t

var lastTextValue:String = ""
Expand All @@ -28,7 +29,6 @@ class ValidationUnit {
self.identifier = identifier
self.lastTextValue = initialText


for type:ValidatorType in self.registeredValidationTypes {
if (type.sendsUpdates) {
NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("validationUnitStatusUpdatedNotification:"), name: ValidatorUpdateNotification, object: type)
Expand Down Expand Up @@ -77,26 +77,32 @@ class ValidationUnit {

func validateText(text:String) {

dispatch_async(self.validationQueue, {

var num_valid = 0

for type:ValidatorType in self.registeredValidationTypes {
let is_valid:Bool = type.isTextValid(text)
num_valid += Int(is_valid)
}

let type_count:Int = self.registeredValidationTypes.count
(num_valid == type_count) ? (self.valid = true) : (self.valid = false)

self.lastTextValue = text

// send notification (on main queue, there be UI work)
dispatch_async(dispatch_get_main_queue(), {
self.validationComplete()
if (self.enabled) {
dispatch_async(self.validationQueue, {
[weak self] in

if let strong_self = self {

var num_valid = 0

for type:ValidatorType in strong_self.registeredValidationTypes {
let is_valid:Bool = type.isTextValid(text)
num_valid += Int(is_valid)
}

let type_count:Int = strong_self.registeredValidationTypes.count
(num_valid == type_count) ? (strong_self.valid = true) : (strong_self.valid = false)

strong_self.lastTextValue = text

// send notification (on main queue, there be UI work)
dispatch_async(dispatch_get_main_queue(), {
strong_self.validationComplete()
})
}

})

})
}

}

Expand Down Expand Up @@ -135,17 +141,21 @@ class ValidationUnit {

@objc func validationUnitStatusUpdatedNotification(notification:NSNotification) {

if let user_info = notification.userInfo {
if let status_num:NSNumber = user_info["status"] as? NSNumber {
let is_valid: Bool = status_num.boolValue ?? false

if (is_valid) {
self.validateText(self.lastTextValue)
} else {
self.valid = false
self.validationComplete()
if (self.enabled) {

if let user_info = notification.userInfo {
if let status_num:NSNumber = user_info["status"] as? NSNumber {
let is_valid: Bool = status_num.boolValue ?? false

if (is_valid) {
self.validateText(self.lastTextValue)
} else {
self.valid = false
self.validationComplete()
}
}
}

}

}
Expand Down
2 changes: 1 addition & 1 deletion Demo/PapersPlease/ViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class ViewController: UIViewController {
self.validationUnit = ValidationUnit(validatorTypes: unit_validator_types, identifier: "email")
NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("validationUnitStatusChange:"), name: ValidationUnitUpdateNotification, object: self.validationUnit)

self.validationUnit.validateText("nico@somewhere")
self.validationUnit.validateText("you@somewhere")


let length_type:ValidatorLengthType = ValidatorLengthType(minimumCharacters:3, maximumCharacters:20)
Expand Down

0 comments on commit 1f44050

Please sign in to comment.