SwiftyFORM
SwiftyFORM 是一个轻量级的 iOS 框架,用于创建表单
由于表单代码难以编写,难以阅读,难以推理。具备较慢的转盘时间。难以维护。

需求
- iOS 12+
- Xcode 12+
- Swift 5.1+
特点
- 提供多种表单项,如 textfield、按钮、滑块
- 一些表单项可以展开/折叠,例如 datepicker、pickerview
- 您可以创建自己的自定义表单项
- 多个行中对齐 textfield
- 表单验证规则引擎
- 在验证存在问题的地方用红色文字显示
- 强类型
- 纯 Swift
- 无第三方依赖
用法
教程 0 - 静态文本
import SwiftyFORM
class MyViewController: FormViewController {
override func populate(_ builder: FormBuilder) {
builder += StaticTextFormItem().title("Hello").value("World")
}
}
教程 1 - 文本字段
import SwiftyFORM
class MyViewController: FormViewController {
override func populate(_ builder: FormBuilder) {
builder += TextFieldFormItem().title("Email").placeholder("Please specify").keyboardType(.emailAddress)
}
}
教程 2 - 打开子视图控制器
import SwiftyFORM
class MyViewController: FormViewController {
override func populate(_ builder: FormBuilder) {
builder += ViewControllerFormItem().title("Go to view controller").viewController(FirstViewController.self)
}
}
高级 - 日期选择器
class DatePickerBindingViewController: FormViewController {
override func populate(_ builder: FormBuilder) {
builder += datePicker
builder += incrementButton
builder += decrementButton
builder += SectionFormItem()
builder += summary
updateSummary()
}
lazy var datePicker: DatePickerFormItem = {
let instance = DatePickerFormItem()
instance.title = "Date"
instance.datePickerMode = .date
instance.behavior = .expandedAlways
instance.valueDidChangeBlock = { [weak self] _ in
self?.updateSummary()
}
return instance
}()
lazy var incrementButton: ButtonFormItem = {
let instance = ButtonFormItem()
instance.title = "Next Day"
instance.action = { [weak self] in
self?.increment()
}
return instance
}()
lazy var decrementButton: ButtonFormItem = {
let instance = ButtonFormItem()
instance.title = "Previous Day"
instance.action = { [weak self] in
self?.decrement()
}
return instance
}()
lazy var summary: StaticTextFormItem = {
return StaticTextFormItem().title("Date").value("-")
}()
func updateSummary() {
summary.value = "\(datePicker.value)"
}
func offsetDate(_ date: Date, days: Int) -> Date {
var dateComponents = DateComponents()
dateComponents.day = days
let calendar = Calendar.current
guard let resultDate = calendar.date(byAdding: dateComponents, to: date) else {
return date
}
return resultDate
}
func increment() {
datePicker.setValue(offsetDate(datePicker.value, days: 1), animated: true)
updateSummary()
}
func decrement() {
datePicker.setValue(offsetDate(datePicker.value, days: -1), animated: true)
updateSummary()
}
}
高级 - 验证
class ChangePasswordViewController: FormViewController {
override func populate(_ builder: FormBuilder) {
builder.navigationTitle = "Password"
builder += SectionHeaderTitleFormItem().title("Your Old Password")
builder += passwordOld
builder += SectionHeaderTitleFormItem().title("Your New Password")
builder += passwordNew
builder += passwordNewRepeated
builder.alignLeft([passwordOld, passwordNew, passwordNewRepeated])
}
lazy var passwordOld: TextFieldFormItem = {
let instance = TextFieldFormItem()
instance.title("Old password").password().placeholder("required")
instance.keyboardType = .numberPad
instance.autocorrectionType = .no
instance.validate(CharacterSetSpecification.decimalDigitCharacterSet(), message: "Must be digits")
instance.submitValidate(CountSpecification.min(4), message: "Length must be minimum 4 digits")
instance.validate(CountSpecification.max(6), message: "Length must be maximum 6 digits")
return instance
}()
lazy var passwordNew: TextFieldFormItem = {
let instance = TextFieldFormItem()
instance.title("New password").password().placeholder("required")
instance.keyboardType = .numberPad
instance.autocorrectionType = .no
instance.validate(CharacterSetSpecification.decimalDigitCharacterSet(), message: "Must be digits")
instance.submitValidate(CountSpecification.min(4), message: "Length must be minimum 4 digits")
instance.validate(CountSpecification.max(6), message: "Length must be maximum 6 digits")
return instance
}()
lazy var passwordNewRepeated: TextFieldFormItem = {
let instance = TextFieldFormItem()
instance.title("Repeat password").password().placeholder("required")
instance.keyboardType = .numberPad
instance.autocorrectionType = .no
instance.validate(CharacterSetSpecification.decimalDigitCharacterSet(), message: "Must be digits")
instance.submitValidate(CountSpecification.min(4), message: "Length must be minimum 4 digits")
instance.validate(CountSpecification.max(6), message: "Length must be maximum 6 digits")
return instance
}()
}
安装
Swift 软件包管理者
随着最新 Xcode 对 Swift 软件包管理器的支持,安装从未如此简单。
打开您的 Xcode 项目 -> 文件
-> Swift 包
-> 添加包依赖...
搜索 SwiftyFORM
并指定您想要的版本。通常,最新标记的发布版是个不错的选择。
CocoaPods
要使用 CocoaPods 将 SwiftyFORM 集成到您的 Xcode 项目中,请在您的 Podfile
中指定以下内容:
source 'https://github.com/CocoaPods/Specs.git'
swift_version = '5.0'
platform :ios, '12.0'
use_frameworks!
target 'MyApp' do
pod 'SwiftyFORM', '~> 1.8'
end
然后,运行以下命令
$ pod install
Carthage
链接到使用 Carthage 显示最小 SwiftyFORM 应用的演示项目.
要使用 Carthage 将 SwiftyFORM 集成到您的 Xcode 项目中,请在您的 Cartfile
中指定它
github "neoneye/SwiftyFORM" ~> 1.8
然后,运行以下命令
$ carthage update
最后,将 SwiftyFORM.framework
(将由 Carthage 在 Carthage/Build/iOS/
下构建)添加到项目中的 链接框架和库(在 通用 选项卡中),并添加一个新的 运行脚本 构建阶段
- 将 shell 设置为
/bin/bash
- 在脚本体中写入
/usr/local/bin/carthage copy-frameworks
- 将
$(SRCROOT)/Carthage/Build/iOS/SwiftyFORM.framework
添加到输入文件
手动
-
打开终端应用并将 cd 到您的 iOS 项目目录
-
仅当您的项目尚未初始化为 git 仓库时,请运行
$ git init
- 通过运行以下命令将
SwiftyFORM
添加为子模块
$ git submodule add https://github.com/neoneye/SwiftyFORM.git
-
在项目导航器中,选择您的应用程序项目并转到 "目标" -> "通用"
-
打开项目文件夹并将
SwiftyFORM.xcodeproj
文件拖到应用程序的 "框架、库和嵌入内容" 选项卡的 "框架、库和嵌入内容" 部分 -
单击 "框架、库和嵌入内容" 部分下的
+
按钮,并添加
SwiftyFORM.framework
通信
- 如果您想贡献,提交一个Pull Request。
- 如果您发现了一个错误,有建议或需要帮助,请开启一个问题。
- 如果您需要帮助,请给我写信:[email protected]