现代应用程序通常包含复杂的数据流和生命周期。Flow是一个Swift库,旨在通过解决三个主要问题来简化这些数据流的构建
- 生命周期管理:管理长生命周期的资源。
- 事件处理:在时间上发出并观察事件。
- 异步操作:处理可能尚未准备好的结果。
- 与RxSwift的比较:为什么您可能选择Flow而不是类似RxSwift的东西。
Flow被精心设计以
- 易于使用:API经过精心设计,易于阅读和易于使用。
- 实用主义:演化和设计用于解决实际问题。
- 可组合:类型以良好的方式组合,使得构建复杂的流程变得容易。
- 高性能:Flow已被高度优化以获得高性能。
- 并发:Flow是线程安全的,并使用一个易于理解的计划器模型。
- 可扩展:Flow被设计为可扩展。
- 强类型:Flow利用Swift强类型以更好地表达意图。
- 正确性:由数百个单元测试支持,并在现场测试了多年。
示例用法
在Flow中,Disposable
协议用于生命周期管理
extension UIView {
func showSpinnerOverlay() -> Disposable {
let spinner = ...
addSubview(spinner)
return Disposer {
spinner.removeFromSuperview()
}
}
}
let disposable = view.showSpinnerOverlay()
disposable.dispose() // Remove spinner
Disposable
资源可以收集到公共的DisposeBag
中
let bag = DisposeBag() // Collects resources to be disposed together
bag += showSpinnerOverlay()
bag += showLoadingText()
bag.dispose() // Will dispose all held resources
并且使用Signal<T>
类型处理事件处理。信号由标准UI组件提供
let bag = DisposeBag()
// UIButton provides a Signal<()>
let loginButton = UIButton(...)
bag += loginButton.onValue {
// Log in user when tapped
}
// UITextField provides a ReadSignal<String>
let emailField = UITextField(...)
let passwordField = UITextField(...)
// Combine and transform signals
let enableLogin: ReadSignal<Bool> = combineLatest(emailField, passwordField)
.map { email, password in
email.isValidEmail && password.isValidPassword
}
// Use bindings and key-paths to update your UI on changes
bag += enableLogin.bindTo(loginButton, \.isEnabled)
最后,Future<T>
类型用于处理异步操作
func login(email: String, password: String) -> Future<User> {
let request = URLRequest(...)
return URLSession.shared.data(for: request).map { data in
User(data: data)
}
}
login(...).onValue { user in
// Handle successful login
}.onError { error in
// Handle failed login
}
这三种类型都附带了许多扩展,允许我们组合复杂的UI流程
class LoginController: UIViewController {
let emailField: UITextField
let passwordField: UITextField
let loginButton: UIButton
let cancelButton: UIBarButtonItem
var enableLogin: ReadSignal<Bool> { /* Introduced above */ }
func login(email: String, password: String) -> Future<User> { /* Introduced above */ }
func showSpinnerOverlay() -> Disposable { /* Introduced above */ }
// Returns future that completes with true if user chose to retry
func showRetryAlert(for error: Error) -> Future<Bool> { ... }
// Will setup UI observers and return a future completing after a successful login
func runLogin() -> Future<User> {
return Future { completion in // Complete the future by calling this with your value
let bag = DisposeBag() // Collect resources to keep alive while executing
// Make sure to signal at once to set up initial enabled state
bag += enableLogin.atOnce().bindTo(loginButton, \.isEnabled)
// If button is tapped, initiate potentially long running login request using input
bag += combineLatest(emailField, passwordField)
.drivenBy(loginButton)
.onValue { email, password in
login(email: email, password: password)
.performWhile {
// Show spinner during login request
showSpinnerOverlay()
}.onErrorRepeat { error in
// If login fails with an error show an alert...
// ...and retry the login request if the user chooses to
showRetryAlert(for: error)
}.onValue { user in
// If login is successful, complete runLogin() with the user
completion(.success(user))
}
}
// If cancel is tapped, complete runLogin() with an error
bag += cancelButton.onValue {
completion(.failure(LoginError.dismissed))
}
return bag // Return a disposable to dispose once the future completes
}
}
}
要求
- Xcode
9.3+
- Swift 4.1
- 平台
- iOS
9.0+
- macOS
10.11+
- tvOS
9.0+
- watchOS
2.0+
- Linux
- iOS
安装
Carthage
github "iZettle/Flow" >= 1.0
Cocoa Pods
platform :ios, '9.0'
use_frameworks!
target 'Your App Target' do
pod 'FlowFramework', '~> 1.0'
end
Swift Package Manager
import PackageDescription
let package = Package(
name: "Your Package Name",
dependencies: [
.Package(url: "https://github.com/iZettle/Flow.git",
majorVersion: 1)
]
)
简介
Flow的各个主要区域的简介可以在以下位置找到:
要想了解更多的可用功能,建议您探索那些有详细文档的源文件。代码补全也应该能帮助您发现信号和未来上许多可用的转换。
了解更多
要了解Flow的API设计背后的信息,我们建议阅读以下文章。它们更深入地探讨了为什么Flow的类型和API看起来和表现是这样的,以及它们是如何实现的,并提供了一些见解。
以及学习如何使用Flow构建其他框架
基于Flow的框架
如果你的目标是iOS,我们强烈推荐你检查这些基于Flow构建的框架
实地测试
Flow在过去的几年中得到了开发、演变和实地测试,并广泛应用于iZettle备受赞誉的点销售应用程序中。
合作
你可以在我们的Slack工作空间与我们合作。提问、分享想法或也许只是参与正在进行中的讨论。要获取邀请,请给我们写信 [email protected]