iOS validation framework with form validation support

Overview

ATGValidator

Carthage compatible CocoaPods GitHub issues GitHub license

ATGValidator is a validation framework written to address most common issues faced while verifying user input data.

You can use it to validate different data types directly, or validate ui components like UITextfield or UITextView, or even add validation support to your custom UI elements. You don't need to subclass native components to get the validation support. UITextField and UITextView has the support out of the box, adding support for any other elements is as simple as adding an extension with protocol conformance to ValidatableInterface.

Best of all, you will get a form validator which consolidates validation results of all ui components added to it.

Sample Project

You can find a sample project with form validation in here.

Installation

Carthage

ATGValidator can be installed using Carthage. To do so simply add the following line to your Cartfile;

github "altayer-digital/ATGValidator" ~> 1.0.0

Cocoapods

To use ATGValidator with cocoapods, add the following line to the Podfile;

pod 'ATGValidator', '~> 1.0'

Usage

First step to add validation is to set the validation rules on the ui element. Any UI element conforming to ValidatableInterface accepts an array of rules.

textfield.validationRules = [
    CharacterSetRule.containsUpperCase(),
    CharacterSetRule.containsLowerCase(),
    CharacterSetRule.containsNumber(),
    CharacterSetRule.containsSymbols()
]

In order to validate a single textfield or textview, you can set a validationHandler closure on the textfield/textview. This will be executed whenever validation is done on the field and result is ready to be applied. An array of errors are passed with result object if the validation result is a failure.

textfield.validationHandler = { result in
    print(result.status, result.errors)
}

You can call validateOnInputChange or validateOnFocusLoss on the ui element to make it perform validations on the corresponding events.

textfield.validateOnInputChange(true)
textfield.validateOnFocusLoss(true)

If you need to aggregate validations of multiple ui elements, you need to create a FormValidator instance, and add all needed elements to the form validator.

let formValidator = FormValidator(handler: { result in
    print(result.status, result.errors)
})
formValidator.add(textfield)

When adding an item to form validator, by default validation will be done on focus loss on those items. But you can change this behaviour for individual fields by mentioning validationPolicy while adding the item to form validator.

formValidator.add(textfield, policy: .onInputChange) // or .onFocusLoss or .none

Whenever the fields have corresponding state changes to their data, form validator's handler closure will be executed with aggregated results automatically.

If you want to perform validation on-demand, you can use the method validateForm(shouldInvokeElementHandlers:completion:) to do it as and when you need it.

Rules

There are 6 types of rules readily available with the framework out of the box. For all rules you can set a custom error while initializing, or call helper methods with(error:)->Rule or with(errorMessage:)->Rule to set it later. If not, all rules have their own default errors from ValidationError enum. You can find them below with each rule description.

EqualityRule

This rule is used to check if the value of the type is equal to the supplied value.

You can create an equality rule by passing the value to be checked against, to the initializer. Optionally you can pass in the mode (equal, notEqual) and an error object to be returned in case of validation failure.

let rule = EqualityRule(value: "text_to_be_verified")
// or 
let rule = EqualityRule(value: "shouldn't_be_equal_text", mode: .notEqual, error: ValidationError.equal)

Default errors:

  • notEqual error for equal mode.
  • equal error for notEqual mode.

RangeRule

You can check if a value is in a specific range with this rule.

let rangeRule = RangeRule(min: 200, max: 299)

Default error: valueOutOfRange

StringLengthRule

You can check for a string's length conformance using this rule. You can pass in whether to trim white spaces and to ignore specific charactersets.

let lengthInRangeRule = StringLengthRule(min: 5, max: 10, trimWhiteSpace: true, ignoreCharactersIn: CharacterSet.symbols)
let minLengthRule = StringLengthRule.min(5)
let maxLengthRule = StringLengthRule.max(5)
let equalLengthRule = StringLengthRule.equal(to: 6)
let requiredStringRule = StringLengthRule.required()

Default errors:

  • default: lengthOutOfRange
  • min: shorterThanMinimumLength
  • max: longerThanMaximumLength
  • equal: notEqual
  • required: shorterThanMinimumLength

StringRegexRule

This rule allows you to perform regular expression matching on strings. You can optionally pass in whether to trim white spaces.

let regexRule = StringRegexRule(regex: "^[0-9]*$")
let emailRule = StringRegexRule.email
let containsNumber = StringRegexRule.containsNumber()
let containsNumbersMinMax = StringRegexRule.containsNumber(min: 2, max: 4)
let containsUpperCase = StringRegexRule.containsUpperCase()
let containsUpperCaseMinMax = StringRegexRule.containsUpperCase(min: 1, max: 2)
let containsLowerCase = StringRegexRule.containsLowerCase()
let containsLowerCaseMinMax = StringRegexRule.containsLowerCase(min: 1, max: 2)
let numbersOnly = StringRegexRule.numbersOnly
let lowerCaseOnly = StringRegexRule.lowerCaseOnly
let upperCaseOnly = StringRegexRule.upperCaseOnly

Default errors:

  • default: regexMismatch
  • email: invalidEmail
  • containsNumber: numberNotFound
  • containsUpperCase: upperCaseNotFound
  • containsLowerCase: lowerCaseNotFound
  • numbersOnly: invalidType
  • lowerCaseOnly: invalidType
  • upperCaseOnly: invalidType

StringValueMatchRule

You can use this rule to check if values from 2 textfields are same. An ideal example is when we check if password field and confirm password field have same contents.

let passwordTextfield: UITextField?
let confirmPasswordTextfield: UITextField?
let valueMatchRule = StringValueMatchRule(base: passwordTextfield)
confirmPasswordTextfield.validationRules = [valueMatchRule]

Default error: notEqual

PaymentCardRule

Payment card rule can be used to check if a supplied card number is a valid payment card number. Luhn's algorithm in combination with regex matching is used to check the validity of the provided card numbers. The rule can be initiated with card types to be checked for, or if not passed will check for all available card types. Available card types are;

  • American Express
  • MasterCard
  • Maestro
  • Visa
  • Visa Electron
  • Discover
  • Diners Club
let cardRule = PaymentCardRule(acceptedTypes: [.amex, .mastercard, .visa, .discover])
// or
let cardRule = PaymentCardRule()
textfield.validationRules = [cardRule]
textfield.validationHandler = { result in
    if let suggestedType = result.value as? PaymentCardType {
        // This is a suggestion from the framework from the input you entered.
        // Please note that having a suggested card type does not mean it's validation is success.
        // You need to handle success/failure separately outside this confition.
    }
}
textfield.validateOnInputChange(true)

Default errors:

  • If card number is not valid: invalidPaymentCardNumber
  • If card number is valid, but is not one of the accepted types: paymentCardNotSupported

In order to identify the card type while you are typing in the number, please use the value field in Result object. If a card type can be suggested from the entered input, the rule will populate the Result.value field with the card type, else it will be populated with the input. Please note that a minimum of 4 characters needs to be entered before the rule starts finding card type suggestions.

Advanced Usage

You can validate common data types out of the box as illustrated below;

"Example with 1 number".satisfyAll(rules: [CharacterSetRule.containsNumber()]).status   // success
"Example with more than 20 characters".satisfyAll(rules: [StringLengthRule.max(20)]).status       // failure
472.satisfyAll(rules: [EqualityRule(value: 472.5)])                                     // failure
301.satisfyAny(rules: [RangeRule(min: 200, max: 299), EqualityRule(value: 304)])        // failure
200.satisfyAny(rules: [RangeRule(min: 200, max: 299), EqualityRule(value: 304)])        // success

As for validating contents of a ui component, please see the example below;

textfield.validationRules = [CharacterSetRule.lowerCaseOnly(ignoreCharactersIn: .whitespaces)]
textfield.validationHandler = { result in
    // This block will be executed with relevant result whenever validation is done.
    print(result.status)    // success
}
// Below line is to manually trigger validation.
textfield.validateTextField()

In order to use form validator, we need to create a FormValidator instance and add required ui elements to the form validator. We can either call the validateForm method directly, or associate a handler closure to the form validator, which will be called when any of the added ui elements' value changes.

let formValidator = FormValidator()
formValidator.add(textfield)
// Add more ui elements here.
formValidator.validateForm { result in
    print(result)
}

Validatable

Validatable is the base protocol which is conformed by any data type that can be validated. Most commonly used types in Swift conforms to Validatable out-of-the-box. Below is the list of all data types that conforms to Validatable out-of-the-box.

  • String
  • Bool
  • Int
  • Double
  • Float
  • CGFloat
  • Date

If you want to add validation support to any other types, you can do so by conforming it to the validatable protocol.

ValidatableInterface

If any custom UI element needs to support validation, it needs to conform to ValidatableInterface protocol. Out of the box, ATGValidator has added this conformance to UITextField and UITextView. Please note that the ValidatableInterface protocol conforms to Validatable protocol. Please see the example for UITextField below to understand how the conformance needs to be implemented.

extension UITextField: ValidatableInterface {

    public var inputValue: Any {
        return text ?? ""
    }

    public func validateOnInputChange(_ validate: Bool) {

        if validate {
            addTarget(self, action: #selector(validateTextField), for: .editingChanged)
        } else {
            removeTarget(self, action: #selector(validateTextField), for: .editingChanged)
        }
    }

    public func validateOnFocusLoss(_ validate: Bool) {

        if validate {
            addTarget(self, action: #selector(validateTextField), for: .editingDidEnd)
            addTarget(self, action: #selector(validateTextField), for: .editingDidEndOnExit)
        } else {
            removeTarget(self, action: #selector(validateTextField), for: .editingDidEnd)
            removeTarget(self, action: #selector(validateTextField), for: .editingDidEndOnExit)
        }
    }

    @objc public func validateTextField() {

        guard let rules = validationRules else {
            return
        }

        var result = satisfyAll(rules: rules)
        if result.status == .success {
            validValue = result.value
        } else if let value = validValue {
            result.value = value
        }
        validationHandler?(result)
        formHandler?(result)
    }
}

Custom Errors

ValidationError is an enum that holds all default validation errors. If you don't want to define an additional error object, and just needs a custom validation error string to be passed, please use ValidationError.custom(errorMessage: String) for it. There are couple of helper methods in Rule to set custom errors easily. They are as given below;

var emailRule = StringRegexRule.email
emailRule = emailRule.with(error: CustomErrorThatConformsToErrorProtocol())
// or
emailRule = emailRule.with(errorMessage: "Email is not correct..!")

ValidatorCache

This is a custom in memory storage used to hold all rules, form handler and validation handlers closures. Please feel free to explore how it is implemented.

Due Credits

When we were faced with the task of finding a good validation framework to be used in our apps, we went through the exploration stage to find available opensource libraries and finally came up with the best one available for the job. If you were in the same situation, you must know which one it is. It's none other than the amazing Validator framework written by Adam Waite. If you haven't seen it already, please head over to that repo and take a look.

Validator uses generics extensively and is the backbone of how the framework works. This made it impossible for us to club together various ui elements and get a unified result for the validations from them. And we really needed form validation in our projects.

So we started writing a framework with protocols as its backbone and to use form validation as the main goal we wanted to achieve. And here is the result, ATGValidator. Please note that the core concepts are heavily influenced by Validator framework and we want to give the due credit to Adam Waite for the excellent work he has done.

Copyright and License

ATGValidator is available under the MIT license. See LICENSE.md for more information.

Contributors

List of contributors is available through GitHub.

You might also like...
🔥 🔥 🔥Support for ORM operation,Customize the PQL syntax for quick queries,Support dynamic query,Secure thread protection mechanism,Support native operation,Support for XML configuration operations,Support compression, backup, porting MySQL, SQL Server operation,Support transaction operations.

🔥 🔥 🔥Support for ORM operation,Customize the PQL syntax for quick queries,Support dynamic query,Secure thread protection mechanism,Support native operation,Support for XML configuration operations,Support compression, backup, porting MySQL, SQL Server operation,Support transaction operations.

APValidators - Codeless solution for form validation in iOS!
APValidators - Codeless solution for form validation in iOS!

APValidators is a codeless solution for form validation. Just connect everything right in Interface Builder and you're done. Supports really complex and extendable forms by allowing to connect validators in tree.

Custom Field component with validation for creating easier form-like UI from interface builder.
Custom Field component with validation for creating easier form-like UI from interface builder.

#YALField Custom Field component with validation for creating easier form-like UI from interface builder. ##Example Project To run the example project

MZFormSheetPresentationController provides an alternative to the native iOS UIModalPresentationFormSheet, adding support for iPhone and additional opportunities to setup UIPresentationController size and feel form sheet.
MZFormSheetPresentationController provides an alternative to the native iOS UIModalPresentationFormSheet, adding support for iPhone and additional opportunities to setup UIPresentationController size and feel form sheet.

MZFormSheetPresentationController MZFormSheetPresentationController provides an alternative to the native iOS UIModalPresentationFormSheet, adding sup

Localization of the application with ability to change language
Localization of the application with ability to change language "on the fly" and support for plural form in any language.

L10n-swift is a simple framework that improves localization in swift app, providing cleaner syntax and in-app language switching. Overview 🌟 Features

Declarative form building framework for iOS
Declarative form building framework for iOS

Formalist Swift framework for building forms on iOS Formalist is a Swift framework for building forms on iOS using a simple, declarative, and readable

Elegant iOS form builder in Swift
Elegant iOS form builder in Swift

Made with ❤️ by XMARTLABS. This is the re-creation of XLForm in Swift. 简体中文 Overview Contents Requirements Usage How to create a Form Getting row valu

Focus text field in SwiftUI dynamically and progress through form using iOS keyboard.
Focus text field in SwiftUI dynamically and progress through form using iOS keyboard.

Focuser Focuser allows to focus SwiftUI text fields dynamically and implements ability move go through the form using Keyboard for iOS 13 and iOS 14.

The most flexible and powerful way to build a form on iOS
The most flexible and powerful way to build a form on iOS

The most flexible and powerful way to build a form on iOS. Form came out from our need to have a form that could share logic between our iOS apps and

A swift package(SPM) with iOS UI component that loads and displays images from remote urls or local assets and displays in a slide-show form with auto scroll feature.

MDBannersView A swift package with an iOS UI component that loads and displays images from remote urls, local assets and displays in a slide-show form

SherlockForms - An elegant SwiftUI Form builder to create a searchable Settings and DebugMenu screens for iOS
SherlockForms - An elegant SwiftUI Form builder to create a searchable Settings and DebugMenu screens for iOS

🕵️‍♂️ SherlockForms What one man can invent Settings UI, another can discover i

nefđź’Ša toolset to ease the creation of documentation in the form of Xcode Playgrounds
nefđź’Ša toolset to ease the creation of documentation in the form of Xcode Playgrounds

nef, short for Nefertiti, mother of Ankhesenamun, is a toolset to ease the creation of documentation in the form of Xcode Playgrounds. It provides com

Former is a fully customizable Swift library for easy creating UITableView based form.
Former is a fully customizable Swift library for easy creating UITableView based form.

Former is a fully customizable Swift library for easy creating UITableView based form. Submitting Issues Click HERE to get started with filing a bug r

ObjectForm - a simple yet powerful library to build form for your class models.
ObjectForm - a simple yet powerful library to build form for your class models.

ObjectForm A simple yet powerful library to build form for your class models. Motivations I found most form libraries for swift are too complicated to

Declarative form validator for SwiftUI.
Declarative form validator for SwiftUI.

SwiftUIFormValidator The world's easiest, most clean SwiftUI form validation. SwiftUIFormValidator A declarative SwiftUI form validation. Clean, simpl

ALO sync allows you to sync resources form an ALO endpoint to your macOS file system.
ALO sync allows you to sync resources form an ALO endpoint to your macOS file system.

ALO sync allows you to sync resources form an ALO endpoint to your macOS file system. Prerequisites macOS 11 No support for search* No suppor

MemeMe, students will create an app that enables a user to take a picture, and add text at the top and bottom to form a meme
MemeMe, students will create an app that enables a user to take a picture, and add text at the top and bottom to form a meme

With this first version of MemeMe, students will create an app that enables a user to take a picture, and add text at the top and bottom to form a meme. The user will be able to share the photo on Facebook and Twitter and also by SMS or email.

Some cells to Form a Pod

CellsGao Example To run the example project, clone the repo, and run pod install from the Example directory first. Requirements Installation CellsGao

Swift library for parsing Extended Backus–Naur Form (EBNF) notation

Gramophone Swift library for parsing Extended Backus–Naur Form (EBNF) notation Integration Swift Package Manager dependencies: [ .package(url: "ht

Comments
  • This is conflict with Result Type of Apple.

    This is conflict with Result Type of Apple.

    Hi. This conflict with Apple Result type. I've fixed this. but there are other issue. it does not work with delegate. when I enable delegate, validationHandler is not working.

    opened by DedicatedDev 0
Owner
null
String (and more) validation for iOS

Swift Validators ?? String validation for iOS. Contents Installation Walkthrough Usage Available validators License ReactiveSwift + SwiftValidators Wa

George Kaimakas 241 Nov 13, 2022
Drop in user input validation for your iOS apps.

Validator Validator is a user input validation library written in Swift. It's comprehensive, designed for extension, and leaves the UI up to you. Here

Adam Waite 1.4k Dec 29, 2022
RxValidator Easy to Use, Read, Extensible, Flexible Validation Checker.

RxValidator Easy to Use, Read, Extensible, Flexible Validation Checker. It can use without Rx. Requirements RxValidator is written in Swift 4.

GeumSang Yoo 153 Nov 17, 2022
Swift Validator is a rule-based validation library for Swift.

Swift Validator is a rule-based validation library for Swift. Core Concepts UITextField + [Rule] + (and optional error UILabel) go into

null 1.4k Dec 29, 2022
🚦 Validation library depends on SwiftUI & Combine. Reactive and fully customizable.

?? Validation library depends on SwiftUI & Combine. Reactive and fully customizable.

Alexo 14 Dec 30, 2022
Validation plugin for Moya.Result

MoyaResultValidate Why? Sometimes we need to verify that the data returned by the server is reasonable, when Moya returns Result.success. JSON returne

Insect_QY 1 Dec 15, 2021
Input Validation Done Right. A Swift DSL for Validating User Input using Allow/Deny Rules

Valid Input Validation Done Right. Have you ever struggled with a website with strange password requirements. Especially those crazy weird ones where

Mathias Quintero 37 Nov 3, 2022
A framework to validate inputs of text fields and text views in a convenient way.

FormValidatorSwift The FormValidatorSwift framework allows you to validate inputs of text fields and text views in a convenient way. It has been devel

ustwo™ 500 Nov 29, 2022
Input Mask is an Android & iOS native library allowing to format user input on the fly.

Migration Guide: v.6 This update brings breaking changes. Namely, the autocomplete flag is now a part of the CaretGravity enum, thus the Mask::apply c

red_mad_robot 548 Dec 20, 2022
iOS validation framework with form validation support

ATGValidator ATGValidator is a validation framework written to address most common issues faced while verifying user input data. You can use it to val

null 51 Oct 19, 2022