A lightweight Swift library for validating and normalizing user input, for example in forms.
Documentation for ValidationKit can be found on GitHub Pages. Documentation is written using DocC, with a documentation catalog included inside the Swift package.
import ValidationKit
// Validators can be combined using the operators `&&` and `||`
lettweetValidator:Validator=.notEmpty && .maxLength(280)lettweet="Hello, world!"letresult= tweetValidator.validate(input: tweet)switch result {case.valid(let value):print("Tweet '\(value)' is valid")case.invalid(let error):print(String(format:"Tweet did not validate: %@", error.localizedDescription))}The built-in validators are:
isEmpty: String must be emptynotEmpty: String must not be emptyminLength(_ length: Int): String length must be greater than or equal...maxLength(_ length: Int): String length must be less than or equal...exactLength(_ length: Int): String length must be exactly...isDate(formatter: DateFormatter): String must be parsable as a date using the given formatterisInThePast: Date must be in the pastanyOf: Value must be one of certain given optionsaccepted: Value must be boolean truehasPrefix: String must have a certain prefix
A custom validator can be implemented as follows. The example uses a regular expression, but of course you are free to use any kind of logic you want.
publicextensionValidator{staticvarisDutchPostalCode:Validator<String,String>{Validator<String,String>{ input iniflet range = input.range(of:#"^\d{4}\s?[a-zA-Z]{2}$"#, options:.regularExpression){letoutput=String(input[range])return.valid(output)}else{return.invalid(.invalidDutchPostalCode)}}}}publicextensionValidationError{staticletinvalidDutchPostalCode=ValidationError(localizedDescription:NSLocalizedString("Invalid Dutch postal code", comment:"Validation error text"))}We can then use it like so:
letpostalCodeValidator:Validator=.notEmpty && .isDutchPostalCode
letresult= postalCodeValidator.validate(input:"2516 AH") // Equals ValidationResult.valid("2516 AH")The input of a validator does not have to be of the same type as its output. For example, this validator converts a string into an array of digits (integers from 0-9).
extensionValidator{
/// Validates whether a string consists of a sequence of digits (0-9).
staticvarnumericCode:Validator<String,[Int]>{Validator<String,[Int]>{ input inletnumericCode:[Int]= input
.map(String.init) // Convert the string to individual characters first
.compactMap(Int.init)if numericCode.count == input.count {return.valid(numericCode)}else{return.invalid(.notNumericCode)}}}}extensionValidationError{staticletnotNumericCode=ValidationError(localizedDescription:NSLocalizedString("Not a numeric code", comment:"Validation error text"))}To validate an 8-digit code, we can use it like so:
letvalidator:Validator=.exactLength(8) && .numericCode
letresult= validator.validate(input:"13374242)result.isValid // Trueresult.value // [1, 3, 3, 7, 4, 2, 4, 2]This library contains localized strings for English and Dutch. Pull requests that add support for additional languages are welcome.
If you desire a different error text for a certain validation, you must write your own validator and validation error. See the files Validators.swift and ValidationError.swift for examples how to do this.
- 1.1.0 - 2024-05-24 - Added email validator
- 1.0.1 - 2023-10-12 - Added isEmpty/notEmpty validators for non-optional string types
- 1.0.0 - 2023-05-25 - After more than two years since the public release, and having been used in multiple production projects, it is time for a 1.0 release!
- 0.0.1 - 2021-03-28 - Initial public release
- 0.0.0 - 2019-12-02 - Initial private version for a project at Q42
ValidationKit is written by Mathijs Bernson and Tim van Steenis.
It is available under the MIT license, so feel free to use it in commercial and non-commercial projects.