GenericValidator 0.0.8

GenericValidator 0.0.8

TestsTested
LangLanguage SwiftSwift
License MIT
ReleasedLast Release Jul 2019
SPMSupports SPM

Maintained by Thibault Klein, Thibault Klein.



  • By
  • Thibault Klein

GenericValidator

Travis build status Cocoapods Compatible Platform Docs

Description

GenericValidator provides helper functions and protocols to help you validate any kind of data that conforms to the Evaluatable and Validatable protocols. The validation protocol takes functions that return a validation result, which can either be valid or invalid. The invalid case contains a custom error that you provide, and the final result will list all the errors that occurred during the validation process.

The framework provides UITextField and String extensions that you can directly use to validate their content.

You can also conform to the Evaluatable and Validatable protocols in your custom types to provide a more custom validation to your code.

For examples, see the Usage section.

This framework was inspired by these blog articles:

Requirements

  • iOS 9+
  • Xcode 10
  • Swift 5+

Installation

To use in your projects, simply add the following line to your Podfile:

pod 'GenericValidator'

You can then use GenericValidator by importing it into your files:

import GenericValidator

Usage

GenericValidator provides 2 extensions that you can use out of the box on UITextField and String. The UITextField extension provides a validation function, and the String extension an evaluation function.

Here is an example where you can use the String extension to evaluate if a string is a valid credit card CVC number, and validate the text field by passing the evaluating function:

enum ValidationError: Error {
    case error(String)
}

typealias CVCValidationResult = ValidationResult<ValidationError>

func isCVCValid(text: String) -> CVCValidationResult {
    let regexp = "^[0-9]{3,4}$"
    if text.evaluate(with: regexp) {
        return .valid
    }

    return .invalid([ValidationError.error("The CVC is invalid")])
}

let cvcTextField = UITextField()
cvcTextField.text = "123"
let result = cvcTextField.validate([isCVCValid]) // result is valid

cvcTextField.text = "12a"
let result = cvcTextField.validate([isCVCValid]) // result is invalid, with error "The CVC is invalid"

You can also conform to the protocols to evaluate and validate your custom types.

Here is an example that describes how to validate a user:

enum ValidationError: Error {
    case error(String)
}

struct User {
    let firstName: String
    let lastName: String
    let age: Int
}

typealias UserValidationResult = ValidationResult<ValidationError>

extension User: Validatable {

    func validate(_ functions: [(User) -> UserValidationResult]) -> UserValidationResult {
		return functions.map({ f in f(self) }).reduce(UserValidationResult.valid) { $0.combine($1) }
    }

}

func isUserNameValid(user: User) -> UserValidationResult {
    let regexp = "[A-Za-z]+$"
    if user.firstName.evaluate(with: regexp)
        && user.lastName.evaluate(with: regexp) {
        return .valid
    }

    return .invalid([ValidationError.error("The user name is invalid")])
}

func isUserAdult(user: User) -> ValidationResult {
    if user.age >= 18 {
        return .valid
    }

    return .invalid([ValidationError.error("The user is not an adult")])
}

let user = User(firstName: "Thibault", lastName: "Klein", age: 26)
let result = user.validate([isUserNameValid, isUserAdult]) // result is valid

let user = User(firstName: "Thibault", lastName: "Klein", age: 17)
let result = user.validate([isUserNameValid, isUserAdult]) // result is invalid with error "The user is not an adult"

let user = User(firstName: "12345", lastName: "Klein", age: 17)
let result = user.validate([isUserNameValid, isUserAdult]) // result is invalid with errors "The user name is invalid" and "The user is not an adult"

Contributing to GenericValidator

To report a bug or enhancement request, feel free to file an issue under the respective heading.

If you wish to contribute to the project, fork this repo and submit a pull request.