Formify 是一个 Swift 库,专为简化表单和输入验证而设计。借助 Formify,您可以轻松验证所有 TextField 或 TextEditor 元素,而无需添加任何特殊的更改或修饰符。
将以下内容添加到您的 Swift 包的 Package.swift 文件中
dependencies: [
.package(url: "https://github.com/sanzaru/formify.git", from: "0.0.1")
]
将以下软件包添加到您的项目中
https://github.com/sanzaru/formify.git
Formify 使用带有 FormifyOperator 运算符的 FormifyField 对象来进行输入管理和验证。所有 FormifyField 对象都带有一个 String 类型的 value 属性。此值可以用作 TextField 或 TextEditor 视图内的绑定。
您可以通过简单地检查字段的 isValid 属性或 errors 数组来检查有效性。
最简单的验证形式是在视图内声明一个状态变量,在 TextField 内使用 FormifyField 的 value,并检查 isValid 属性
...
@State private var formField = FormifyField(operators: [.required, .pattern("[A-Za-z ]+")])
...
TextField("", text: $formField.value)
.textFieldStyle(.plain)
...
Button { } label: {
Text("Submit")
}
.disabled(!formField.isValid)
...
注意
您还可以将 FormifyField 作为 @Binding 传递到视图中,或者在 @ObservableObject 中将该对象用作 @Published 变量。有关更多信息,请参见示例。
| 名称 | 描述 | 示例 |
|---|---|---|
| .required | 如果设置,则该字段变为必填项,不能为空。 | .required |
| .minLength(Int) | 如果设置,则该值必须长于提供的长度。 | .minLength(10) |
| .maxLength(Int) | 如果设置,则该值必须短于提供的长度。 | .maxLength(10) |
| .pattern(String) | 如果设置,则该值必须与提供的正则表达式匹配。 | .pattern("[a-zA-Z]") |
| 如果设置,则该值必须与电子邮件地址的内部正则表达式匹配。 | .email |
|
| .phone | 如果设置,则该值必须与电话号码的内部正则表达式匹配。 | .phone |
| .urlWithScheme | 如果设置,则该值必须与带有 scheme 的 URL 的内部正则表达式匹配(例如 https://example.com, file://some-file)。 | .urlWithScheme |
| .urlNoScheme | 如果设置,则该值必须与不带 scheme 的 URL 的内部正则表达式匹配(例如 localhost, example.com)。 | .urlNoScheme |
| .disableTrimming | 如果设置,则禁用自动修剪空格和换行符。 | .disableTrimming |
| .custom | 如果设置,则给定的验证处理程序 (String) -> Bool 将用于验证。 |
.custom({ $0 == "someValue" }) |
以下示例展示了一个简单的视图,其中包含一个表单,该表单包含三个字段:姓名、电子邮件地址和自定义值。姓名和电子邮件字段是必填项,并根据特定模式进行验证。姓名字段还具有最小和最大长度验证,而自定义字段仅为必填项,没有额外的验证
import SwiftUI
import Formify
struct ContentView: View {
struct FormFields {
var name = FormifyField(operators: [.required, .minLength(10), .maxLength(20), .pattern("[A-Za-z ]+")])
var email = FormifyField("foo@bar.com", operators: [.pattern("[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}")])
var custom = FormifyField("Preset value", operators: [.required])
var isValid: Bool {
name.isValid && email.isValid && custom.isValid
}
}
@State private var formFields = FormFields()
var body: some View {
NavigationStack {
Form {
// Name text field
VStack(alignment: .leading) {
Text("Name*")
.foregroundColor(.teal)
TextField("John Doe", text: $formFields.name.value)
.textFieldStyle(.plain)
.modifier(FormValidationErrorWrapperModifier(formField: $formFields.name))
}
// Email text field
VStack(alignment: .leading) {
Text("Email*")
.foregroundColor(.teal)
TextField("example@mail.com", text: $formFields.email.value)
.textFieldStyle(.plain)
.modifier(FormValidationErrorWrapperModifier(formField: $formFields.email))
}
// Custom text field
VStack(alignment: .leading) {
Text("Custom")
.foregroundColor(.teal)
TextField("Some value", text: $formFields.custom.value)
.textFieldStyle(.plain)
.modifier(FormValidationErrorWrapperModifier(formField: $formFields.custom))
}
}
.navigationTitle("Example Form")
.toolbar {
ToolbarItem(placement: .topBarTrailing) {
Button { print("Submit") } label: {
Text("Submit")
}
.disabled(!formFields.isValid)
}
}
}
}
}
此外,以下示例展示了一个简单的 ViewModifier,它可以包装所有错误并在 TextField 下方显示消息
import SwiftUI
import Formify
struct FormValidationErrorWrapperModifier: ViewModifier {
@Binding var formField: FormifyField
func body(content: Content) -> some View {
VStack(alignment: .leading) {
content
let errors = formField.errors
if !errors.isEmpty, formField.isTouched {
ForEach(errors, id: \.self) { error in
Group {
switch error {
case .pattern: Text("Invalid pattern")
case .required: Text("Required")
case .minLength(let length): Text("Min length \(length) / \(formField.minLength ?? 0)")
case .maxLength(let length): Text("Max length \(length) / \(formField.maxLength ?? 0)")
}
}
.font(.caption)
.foregroundColor(.red)
}
}
}
}
}