测试已测试 | ✓ |
Lang语言 | SwiftSwift |
许可证 | MIT |
发布上次发布 | 2017年4月 |
SwiftSwift版本 | 3.0.2 |
SPM支持SPM | ✗ |
依赖项 | |
RxSwift | ~> 3.0 |
RealmSwift | ~> 2.0 |
使用Realm和RxSwift实现的一种持久的单向数据流。RxStateFlow提供了一种架构,核心思想是代码围绕应用程序状态的一个Model
构建,一种更新模型的方法以及一种查看模型的方法。
使用RxStateFlow可以非常容易地使应用程序的状态持久(在应用程序启动之间),反应式且可以跨类和线程访问。
由于框架使用Realm,所以状态
指的是任何满足StateObject
的项,实际上是Realm模型的子类 - 这样应用程序的状态总是在应用程序启动之间持久存在,并且可以在任何线程上观察到。
class AppState: StateObject {
fileprivate(set) dynamic var counter: Int = 0
override func react(to event: Event) {
switch event {
case CounterEvent.increase:
counter += 1
default:
break
}
}
}
使用组合创建更复杂状态。父状态可以按照它们希望的任何方式对事件做出反应,尽管这通常涉及将默认行为委托给子状态。
class AnotherObject: StateObject {
fileprivate(set) dynamic var value: String = ""
override func react(to event: Event) {
}
}
class AppState: StateObject {
fileprivate(set) dynamic var counter: Int = 0
fileprivate(set) dynamic var another: AnotherObject
override func react(to event: Event) {
another.react(to: event)
}
}
RxStateFlow只允许通过事件进行状态更改。事件是描述状态更改的小数据片段,不包含任何代码。它们被消费者存储并由根状态上的react(to event: Event)
方法转发。该方法将通过为每个事件实现不同的状态更改来处理事件。
可以触发状态更新。事件可以是结构体或枚举。以下是一些示例
最简单的形式。
struct UpdateCounter: Event { }
作为枚举。
enum CounterEvent: Event {
case increase
case decrease
case reset
}
将一些数据与事件一起传递。
struct UpdateCounter: Event {
let value: Int
}
泛型也可以。
struct Update<T>: Event {
var value: T
}
命令有助于以安全且一致的方式与存储交互,其中需要在以后点向存储分派事件。对于网络、数据库操作或任何其他异步操作非常有用。
此外,它可以用来执行条件调度,而不是在视图中或视图控制器中直接检查必要的状态,这避免了视图中的任何复杂业务逻辑。
struct IncreaseCounter: Command {
func execute(state: AppState, store: Store<AppState>) {
if state.counter < 10 {
store.dispatch(event: CounterEvent.increase)
}
}
}
// to dispatch a command
store.dispatch(command: IncreaseCounter())
存储应用程序状态,负责调度事件和命令。接收到的事件会通过在根状态上调用 react(to event: Event)
来更新状态。每当存储中的状态改变时,存储将通知所有观察者。
创建一个供整个应用程序使用的共享全局存储。
let store = Store<AppState>()
注意:在 react(to event: Event)
中不要产生副作用,不要进行异步调用,或使用不纯的函数,如 NSDate()
。
在 RxStateFlow 应用中,当你的状态改变时,你的视图会更新。你的视图成为当前应用程序状态的简单可视化。
通过订阅状态,我们确保当这个视图控制器可见时,它与最新的应用程序状态保持同步。在初次订阅时,存储会将最新的状态发送给订阅者的更新函数。
class ViewController: UIViewController {
internal var bag = DisposeBag()
override func viewDidLoad() {
super.viewDidLoad()
// Subscribe to store changes
store.state.asDriver().drive(onNext: { state in
// update UI
}).addDisposableTo(bag)
}
}
中间件可以在事件周围执行任务。当每次传递事件时,中间件都会被调用,在更新应用程序状态之前和之后。中间件不允许修改状态,但它会得到一个包含事件的状态副本。这对于日志记录、分析、错误处理和其他副作用很有用。
struct LoggingMiddleware: Middleware {
func before(event: Event, state: AppState) {
switch event {
case CounterEvent.increase:
print("About to increase counter")
default:
break
}
}
func after(event: Event, state: AppState) {
switch event {
case CounterEvent.increase:
print("Counter increased")
default:
break
}
}
}
按照以下 3 个步骤运行示例项目:克隆 RxStateFlow 仓库,打开 RxStateFlow 仓库,并运行 Example 项目。
示例项目包括