Form 是一个用于构建和样式化 UIs 的 iOS Swift 库。一套高度可组合的工具箱,用于解决常见 UI 相关问题,例如:
- 表单 - 使用混合行类型构建类似表格的 UIs。
- 表格 - 填充表格和集合视图。
- 布局 - 布局和更新视图层次结构。
- 样式 - UI 组件的样式。
- 键盘 - 调整键盘。
- 值 - 显示和编辑自定义类型。
尽管 Form 很灵活,但它也有自己的观点,并有首选的构建 UIs 的方式
- 以编程方式构建和布局 UI。
- 使用响应式编程处理事件。
- 促进小型可重用组件和扩展到子类。
- 尽量使用值类型进行显式和声明式编程。
Form 框架基于 Flow 框架,用于处理事件处理和生命周期管理。
示例用法
为了展示 Form 的主要理念,我们将基于 `Message` 模型构建一个简单的消息应用。
struct Message: Hashable {
var title: String
var body: String
}
该应用程序将包括一个显示我们的消息的视图以及一个用于编写新消息的视图。
Form 使构建类似表单的界面变得容易,这些界面的样式和布局类似于表格视图,这在 iOS 应用程序中非常常见。
extension UIViewController {
func presentComposeMessage() -> Future<Message> {
self.displayableTitle = "Compose Message"
let form = FormView()
let section = form.appendSection()
let title = section.appendRow(title: "Title").append(UITextField(placeholder: "title"))
let body = section.appendRow(title: "Body").append(UITextField(placeholder: "body"))
let isValid = combineLatest(title, body).map {
!$0.isEmpty && !$1.isEmpty
}
let save = navigationItem.addItem(UIBarButtonItem(system: .save), position: .right)
let cancel = navigationItem.addItem(UIBarButtonItem(system: .cancel), position: .left)
return Future { completion in
let bag = DisposeBag()
bag += isValid.atOnce().bindTo(save, \.enabled)
bag += save.onValue {
let message = Message(title: title.value, body: body.value)
completion(.success(message))
}
bag += cancel.onValue {
completion(.failure(CancelError()))
}
bag += self.install(form) { scrollView in
bag += scrollView.chainAllControlResponders(shouldLoop: true, returnKey: .next)
title.provider.becomeFirstResponder()
}
return bag
}
}
}
Form 扩展了多个 UI 组件,它们接受一个样式参数的初始化器,通常具有默认值,并且可以被您的应用程序全局覆盖。
上面的表单是用堆叠视图构建的,Form 还提供辅助功能来填充 `UITableView`,以便在您具有更大的或动态的表格时提高性能。
extension Message: Reusable {
static func makeAndConfigure() -> (make: RowView, configure: (Message) -> Disposable) {
let row = RowView(title: "", subtitle: "")
return (row, { message in
row.title = message.title
row.subtitle = message.body
// Returns a `Disposable` to keep activities alive while being presented.
return NilDisposer() // No activities.
})
}
}
extension UIViewController {
// Returns a `Disposable` to keep activities alive while being presented.
func present(messages: ReadSignal<[Message]>) -> Disposable {
displayableTitle = "Messages"
let bag = DisposeBag()
let tableKit = TableKit<EmptySection, Message>(bag: bag)
bag += messages.atOnce().onValue {
tableKit.set(Table(rows: $0))
}
bag += install(tableKit)
return bag
}
}
表单和表格都使用相同的样式,因此您可以无缝地混合表和表格,以获得两者的好处。
要求
- Xcode
9.3+
- Swift 5
- iOS
9.0+
安装
Carthage
github "iZettle/Form" >= 3.0
Cocoa Pods
platform :ios, '9.0'
use_frameworks!
target 'Your App Target' do
pod 'FormFramework', '~> 3.0'
end
简介
- 表单 - 使用混合行类型构建类似表格的 UIs。
- 表格 - 用你的模型类型填充表格和集合视图。
- 布局 - 与布局和视图层次结构一起工作。
- 样式 - 创建自定义 UI 样式。
- 键盘 - 调整 UI 以适应键盘。
- 值 - 显示和编辑自定义类型。
本地化
Form 的许多 API 用于处理端用户显示文本,接受符合 DisplayableString
的值,而不是默认字符串。当使用这些 API 作为 String
时,您仍然可以使用默认字符串,因为 String
已经符合 DisplayableString
。但是,如果您的应用程序需要本地化,我们强烈建议您实现自己的本地化字符串类型,例如
struct Localized: DisplayableString {
var key: String
var displayValue: String { return translate(key) }
}
let label = UILabel(value: Localized("InfoKey"))
或者如果您更喜欢简洁的风格
prefix operator §
prefix func §(key: String) -> Localized {
return Localized(key: key)
}
let label = UILabel(value: §"InfoKey")
演示框架
我们强烈建议您也检查一下演示框架。表单和演示框架是紧密协作开发的,并共享许多相同的设计理念。
实地测试
表单经历了多年的开发、演变和实地测试,并在 iZettle 的高评价销售点应用中得到广泛使用。
合作
您可以在我们的 Slack 工作空间与我们合作。提问、分享想法,或者在持续讨论中参与。要获取邀请,请给我们写信 [email protected]