- April 27, 2024
- Mins Read
A Swift Package to easily validate your properties using Property Wrappers 👮
import SwiftUI
import ValidatedPropertyKit
struct LoginView: View {
@Validated(!.isEmpty && .isEmail)
var mailAddress = String()
@Validated(.range(8…))
var password = String()
var body: some View {
List {
TextField(
“E-Mail”,
text: self.$mailAddress
)
if self._mailAddress.isInvalidAfterChanges {
Text(verbatim: “Please enter a valid E-Mail address.”)
}
TextField(
“Password”,
text: self.$password
)
if self._password.isInvalidAfterChanges {
Text(verbatim: “Please enter a valid password.”)
}
Button {
print(“Login”, self.mailAddress, self.password)
} label: {
Text(verbatim: “Submit”)
}
.validated(
self._mailAddress,
self._password
)
}
}
}
To integrate using Apple’s Swift Package Manager, add the following as a dependency to your Package.swift
:
dependencies: [
.package(url: “https://github.com/SvenTiigi/ValidatedPropertyKit.git”, from: “0.0.6”)
]
Or navigate to your Xcode project then select Swift Packages
, click the “+” icon and search for ValidatedPropertyKit
.
If you prefer not to use any of the aforementioned dependency managers, you can integrate ValidatedPropertyKit into your project manually. Simply drag the Sources
Folder into your Xcode project.
The @Validated
attribute allows you to specify a validation alongside to the declaration of your property.
Note: @Validated supports SwiftUI View updates and will basically work the same way as @State does.
@Validated(!.isEmpty)
var username = String()
@Validated(.hasPrefix(“https”))
var avatarURL: String?
If @Validated
is applied on an optional type e.g. String?
you can specify whether the validation should fail or succeed when the value is nil
.
@Validated(
.isURL && .hasPrefix(“https”),
isNilValid: true
)
var avatarURL: String?
By default the argument
nilValidation
is set to.constant(false)
In addition the SwiftUI.View
extension validated()
allows you to disable or enable a certain SwiftUI.View
based on your @Validated
properties. The validated()
function will disable the SwiftUI.View
if at least one of the passed in @Validated
properties evaluates to false
.
@Validated(!.isEmpty && .contains(“@”))
var mailAddress = String()
@Validated(.range(8…))
var password = String()
Button(
action: {},
label: { Text(“Submit”) }
)
.validated(self._mailAddress && self._password)
By using the underscore notation you are passing the
@Validated
property wrapper to thevalidated()
function
Each @Validated
attribute will be initialized with a Validation
which can be initialized with a simple closure that must return a Bool
value.
@Validated(.init { value in
value.isEmpty
})
var username = String()
Therefore, ValidatedPropertyKit comes along with many built-in convenience functions for various types and protocols.
@Validated(!.contains(“Android”, options: .caseInsensitive))
var favoriteOperatingSystem = String()
@Validated(.equals(42))
var magicNumber = Int()
@Validated(.keyPath(\.isEnabled, .equals(true)))
var object = MyCustomObject()
Head over the Predefined Validations section to learn more
Additionally, you can extend the Validation
via conditional conformance to easily declare your own Validations.
extension Validation where Value == Int {
/// Will validate if the Integer is the meaning of life
static var isMeaningOfLife: Self {
.init { value in
value == 42
}
}
}
And apply them to your validated property.
@Validated(.isMeaningOfLife)
var number = Int()
You can access the isValid
state at anytime by using the underscore notation to directly access the @Validated
property wrapper.
@Validated(!.isEmpty)
var username = String()
username = “Mr.Robot”
print(_username.isValid) // true
username = “”
print(_username.isValid) // false
Validation Operators allowing you to combine multiple Validations like you would do with Bool values.
// Logical AND
@Validated(.hasPrefix(“https”) && .hasSuffix(“png”))
var avatarURL = String()
// Logical OR
@Validated(.hasPrefix(“Mr.”) || .hasPrefix(“Mrs.”))
var name = String()
// Logical NOT
@Validated(!.contains(“Android”, options: .caseInsensitive))
var favoriteOperatingSystem = String()
The ValidatedPropertyKit
comes with many predefined common validations which you can make use of in order to specify a Validation
for your validated property.
KeyPath
The keyPath
validation will allow you to specify a validation for a given KeyPath
of the attributed property.
@Validated(.keyPath(\.isEnabled, .equals(true)))
var object = MyCustomObject()
Strings
A String property can be validated in many ways like contains
, hasPrefix
and even RegularExpressions
.
@Validated(.isEmail)
var string = String()
@Validated(.contains(“Mr.Robot”))
var string = String()
@Validated(.hasPrefix(“Mr.”))
var string = String()
@Validated(.hasSuffix(“OS”))
var string = String()
@Validated(.regularExpression(“[0-9]+$”))
var string = String()
Equatable
A Equatable
type can be validated against a specified value.
@Validated(.equals(42))
var number = Int()
Sequence
A property of type Sequence
can be validated via the contains
or startsWith
validation.
@Validated(.contains(“Mr.Robot”, “Elliot”))
var sequence = [String]()
@Validated(.startsWith(“First Entry”))
var sequence = [String]()
Collection
Every Collection
type offers the isEmpty
validation and the range
validation where you can easily declare the valid capacity.
@Validated(!.isEmpty)
var collection = [String]()
@Validated(.range(1…10))
var collection = [String]()
Comparable
A Comparable
type can be validated with all common comparable operators.
@Validated(.less(50))
var comparable = Int()
@Validated(.lessOrEqual(50))
var comparable = Int()
@Validated(.greater(50))
var comparable = Int()
@Validated(.greaterOrEqual(50))
var comparable = Int()
Horizon SDK is a state of the art real-time video recording / photo shooting iOS library. Some of the features ...