RxStateFlow 1.0.3

RxStateFlow 1.0.3

测试已测试
Lang语言 SwiftSwift
许可证 MIT
发布上次发布2017年4月
SwiftSwift版本3.0.2
SPM支持SPM

Miroslav Valkovic-Madjer维护。



 
依赖项
RxSwift~> 3.0
RealmSwift~> 2.0
 

简介

使用RealmRxSwift实现的一种持久的单向数据流。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
        }
    }
}

需求

  • iOS 9.0+
  • Xcode 8.1+
  • Swift 3

示例

按照以下 3 个步骤运行示例项目:克隆 RxStateFlow 仓库,打开 RxStateFlow 仓库,并运行 Example 项目。

示例项目包括

  • 事件
  • 命令(条件调度)
  • 历史中间件
  • 日志记录中间件
  • 错误处理

安装

致谢