Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 9 additions & 9 deletions Classes/Validator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,23 +12,23 @@ import UIKit
public typealias ValidatorPredicate = (Any?, [Any?]) -> Bool

/// `Validator`
public struct Validator {

public class Validator {
/// A control to be validated
var control: Validatable?

/// A method that validates the control
var predicate: ValidatorPredicate

/// A list of other parameters to pass to predicate
var predicateParameters: [Any?]

/// A placeholder that will display error
var errorPlaceholder: ValidationErrorDisplayable?

/// An error message to be shown if the control fails validation
var errorMessage: String

/// Creates `Validator` instance
///
/// - Parameters:
Expand All @@ -44,13 +44,13 @@ public struct Validator {
self.errorPlaceholder = errorPlaceholder
self.errorMessage = errorMessage
}

/**
Performs validation of the control
- Returns: `True` if the control passes validation
*/
public func validate() -> Bool {
return predicate(control?.getValue(), predicateParameters)
}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// ValidatorViewController+AlphaNumeric.swift
// ValidatorController+AlphaNumeric.swift
// EGFormValidator
//
// Created by Evgeny Gushchin on 31/12/16.
Expand All @@ -9,7 +9,7 @@
import UIKit

/// The extension adds AlphaNumeric validator
public extension ValidatorViewController {
public extension ValidatorController {
/**
Validator's predicate: verifies if given value contains only digits or letters

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// ValidatorViewController+DigitsOnly.swift
// ValidatorController+DigitsOnly.swift
// EGFormValidator
//
// Created by Evgeny Gushchin on 19/12/16.
Expand All @@ -9,7 +9,7 @@
import UIKit

/// The extension adds DigitsOnly validator
public extension ValidatorViewController {
public extension ValidatorController {
/**
Validator's predicate: verifies if given value contains only digits

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// ValidatorViewController+Email.swift
// ValidatorController+Email.swift
// EGFormValidator
//
// Created by Evgeny Gushchin on 09/12/16.
Expand All @@ -9,7 +9,7 @@
import UIKit

/// The extension adds Email validator
public extension ValidatorViewController {
public extension ValidatorController {

/**
Validator's predicate: verifies if given value is a valid email address
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// ValidatorViewController+EqualTo.swift
// ValidatorController+EqualTo.swift
// EGFormValidator
//
// Created by Evgeny Gushchin on 09/12/16.
Expand All @@ -9,7 +9,7 @@
import UIKit

/// The extension adds EqualTo validator
public extension ValidatorViewController {
public extension ValidatorController {
/**
Validator's predicate: verifies if given value is equal to another control's value

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// ValidatorViewController+Mandatory.swift
// ValidatorController+Mandatory.swift
// EGFormValidator
//
// Created by Evgeny Gushchin on 09/12/16.
Expand All @@ -9,7 +9,7 @@
import UIKit

/// The extension adds Mandatory validator
public extension ValidatorViewController {
public extension ValidatorController {

/**
Validator's predicate: verifies if given value is not empty
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// ValidatorViewController+Minlength.swift
// ValidatorController+Minlength.swift
// EGFormValidator
//
// Created by Evgeny Gushchin on 09/12/16.
Expand All @@ -9,7 +9,7 @@
import UIKit

/// The extension adds Minlength validator
extension ValidatorViewController {
extension ValidatorController {

/**
Validator's predicate: verifies if given value has at least `value` characters
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// ValidatorViewController+Regexp.swift
// ValidatorController+Regexp.swift
// EGFormValidator
//
// Created by Evgeny Gushchin on 08/01/17.
Expand All @@ -9,7 +9,7 @@
import UIKit

/// The extension adds Regexp validator
public extension ValidatorViewController {
public extension ValidatorController {
/**
Validator's predicate: verifies if a given value matches the pattern

Expand Down
25 changes: 25 additions & 0 deletions Classes/ValidatorController.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//
// ValidatorController.swift
// EGFormValidator
//
// Created by Roberto Casula on 11/05/18.
// Copyright © 2018 Evgeny Gushchin. All rights reserved.
//

import UIKit

/// Declares validation condition
public typealias ValidatorCondition = () -> Bool

public protocol ValidatorController: class {
var validators: [Validator] { get set }
var validatorConditions: [ValidatorCondition] { get set }

/// Read-only property that stores the first failed in case if you need to scroll up your view and to show the invalid control
var firstFailedControl: UIView? { get set }

func add(validator: Validator)
func add(validator: Validator, condition: @escaping ValidatorCondition)

func validate() -> Bool
}
95 changes: 65 additions & 30 deletions Classes/ValidatorViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,10 @@

import UIKit

/// Declares validation condition
public typealias ValidatorCondition = () -> Bool

/// Adds to `UIViewController` validation functionality
open class ValidatorViewController: UIViewController {
// MARK - VALIDATION
private var validators = [Validator]()
private var validatorConditions = [ValidatorCondition]()

/// Adds to subclasses of `UIViewController` validation functionality
public extension ValidatorController where Self: UIViewController {

/**
Adds a new unconditional validator to a validation list
- Parameter validator: A validator to be added to the validation list
Expand All @@ -29,7 +24,7 @@ open class ValidatorViewController: UIViewController {
return true
}
}

/**
Adds a new conditional validator to a validation list
- Parameter validator: A validator to be added to the validation list
Expand All @@ -40,52 +35,54 @@ open class ValidatorViewController: UIViewController {
If condition returns `false` the validator will mark the field as valid.
*/
public func add(validator: Validator, condition: @escaping ValidatorCondition) {
// let weakValidator = WeakRef(value: validator)
// debugPrint(weakValidator, weakValidator.value, validator)
validators.append(validator)
validatorConditions.append(condition)
debugPrint(validators.count, validatorConditions.count)
}

/// Read-only property that stores the first failed in case if you need to scroll up your view and to show the invalid control
public private(set) var firstFailedControl: UIView?


/**
Execute all predicates of all validators i.e. performs validation of a form
- Returns: Tells if _all validators_ are valid or not.
*/
public func validate() -> Bool {
var formIsValid = true

// a set of invalidated controls
var inValidatedControls = Set<UIView>()
self.firstFailedControl = nil

for (index, validator) in validators.enumerated() {
var isControlValid = false

// debugPrint(validator, validator.value)
// all controls should be UIViews so there shouldn't be any problem
if let control = validator.control as? UIView {

let val = validator
if /*let val = validator.value,*/
let control = val.control as? UIView {

// validate it again only if it passed previous validation
if !inValidatedControls.contains(control) {
// the control is not validated yet
// or it has been already validated and it passed all its previus validations

// check conditions
if validatorConditions[index]() {
// get validation result
isControlValid = validator.validate()

isControlValid = val.validate()
if isControlValid {
// control is valid
validator.control?.setValidation?(state: .valid)
validator.errorPlaceholder?.setErrorMessage(errorMessage: nil)
val.control?.setValidation?(state: .valid)
val.errorPlaceholder?.setErrorMessage(errorMessage: nil)
} else {
// control is not valid
validator.control?.setValidation?(state: .error)
validator.errorPlaceholder?.setErrorMessage(errorMessage: validator.errorMessage)

val.control?.setValidation?(state: .error)
val.errorPlaceholder?.setErrorMessage(errorMessage: val.errorMessage)
// add the control to inValidatedControls set
inValidatedControls.insert(control)

if self.firstFailedControl == nil {
self.firstFailedControl = control
}
Expand All @@ -94,16 +91,54 @@ open class ValidatorViewController: UIViewController {
// validator was executed
// control is valid
isControlValid = true
validator.control?.setValidation?(state: .valid)
validator.errorPlaceholder?.setErrorMessage(errorMessage: nil)
val.control?.setValidation?(state: .valid)
val.errorPlaceholder?.setErrorMessage(errorMessage: nil)
}
}
}

// add the current control validation results to output
formIsValid = formIsValid && isControlValid
}
return formIsValid
}
}

open class ValidatorViewController: UIViewController, ValidatorController {
public var firstFailedControl: UIView?

public var validators: [Validator] = [Validator]()
public var validatorConditions = [ValidatorCondition]()

open override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
validators = []
validatorConditions = []
}
}

open class ValidatorTableViewController: UITableViewController, ValidatorController {
public var firstFailedControl: UIView?

public var validators: [Validator] = [Validator]()
public var validatorConditions = [ValidatorCondition]()

open override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
validators = []
validatorConditions = []
}
}

open class ValidatorTabBarController: UITabBarController, ValidatorController {
public var firstFailedControl: UIView?

public var validators: [Validator] = [Validator]()
public var validatorConditions = [ValidatorCondition]()

open override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
validators = []
validatorConditions = []
}
}
Loading