返回

源代码解读:ReactorKit 的状态管理模型

IOS

ReactorKit 源码解读

前言

ReactorKit 是构建于 RxSwift 生态系统之上的一个状态管理框架。它虽然被称为框架,但其实封装非常轻量。本文将深入 ReactorKit 源码,分享一些阅读所得。

协议与运行时

为了让 Swift 的协议扩展具备「给实现协议的人动态添加属性(依赖)」的能力,ReactorKit 采用了运行时的方案。它首先定义了一个 AssociatedType Protocol,即 AssociatedTypeBox

public protocol AssociatedTypeBox: AnyObject {
    var associatedType: Any.Type { get set }
}

然后,它使用运行时关联对象(Associated Object)将 AssociatedTypeBox 与实现协议的类型关联起来。在 extension AssociatedTypeBox where Self: Protocol 中,它添加了一个名为 associatedType 的计算属性,用于获取或设置关联的类型:

extension AssociatedTypeBox where Self: Protocol {
    var associatedType: Any.Type {
        get {
            return objc_getAssociatedObject(self, &associatedTypeKey) as? Any.Type ?? Self.self
        }
        set {
            objc_setAssociatedObject(self, &associatedTypeKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
    }
}

有了这个基础,ReactorKit 就可以动态地为协议扩展添加属性和方法。例如,对于 Reactor 协议,它添加了 associatedType 属性,用于获取与之关联的 State 类型:

extension Reactor: AssociatedTypeBox { }

状态管理

ReactorKit 的核心概念是「状态管理」。它将状态视为一个不可变的值,并通过 Reactor 对象进行管理。Reactor 对象负责根据动作(Action)更新状态,并通知观察者有关状态变化的信息。

class Reactor<State: Equatable> {
    // ...

    var currentState: State {
        // ...
    }

    func mutate(action: Action) -> State? {
        // ...
    }

    // ...
}

动作处理

ReactorKit 将用户交互或其他事件抽象为「动作」(Action)。动作是一个枚举,可以表示各种事件,例如按钮点击、网络请求或用户输入。

enum MyAction: Action {
    case buttonTapped
    case networkRequest(String)
    case userInput(String)
}

Reactor 对象负责处理这些动作,并根据动作更新状态。动作处理逻辑通常写在 mutate(action:) 方法中。

func mutate(action: MyAction) -> State? {
    switch action {
    case .buttonTapped:
        // ...
    case .networkRequest(let url):
        // ...
    case .userInput(let input):
        // ...
    }
}

绑定视图

ReactorKit 提供了 bind(to:) 方法,用于将 Reactor 对象绑定到视图。绑定后,视图将自动订阅 Reactor 对象的状态更新,并在状态变化时更新其 UI。

// ...

let reactor = MyReactor()
let view = MyView()

reactor.bind(to: view)

优势与局限

ReactorKit 具有以下优势:

  • 清晰的状态管理模型: 它明确地将状态与业务逻辑分离,使代码更易于理解和维护。
  • 可测试性: Reactor 对象是可测试的,可以独立于视图进行测试。
  • 轻量级封装: 它只提供了必要的抽象,避免了不必要的复杂性。

ReactorKit 也有一些局限:

  • 学习曲线: 需要一些时间来理解其独特的编程模型。
  • 灵活性: 它是一种结构化的状态管理方式,可能不适合所有应用程序。
  • 性能: 在复杂应用程序中,动态添加属性和方法可能会影响性能。

结论

ReactorKit 是一个轻量级且强大的状态管理框架,它提供了清晰的状态管理模型、可测试性和灵活性。虽然它有一定的学习曲线和局限,但对于需要清晰且可维护的状态管理的应用程序来说,它是一个有价值的选择。