作者 - 图1

Swift CocoaPods Platform Build Status Codecov CocoaDocs

作者

Jeon SuyeolReactorKit 的作者。他也发布了一些富有创造性的框架,如 ThenURLNavigatorSwiftyImage 以及一些开源项目 RxTodoDrrrible。他也是多个组织的成员 RxSwiftCommunityMoyaSwiftKorea

介绍

ReactorKit 结合了 Flux响应式编程。用户行为和页面状态都是通过序列相互传递。这些序列都是单向的:页面只能发出用户行为,然而反应器(Reactor)只能发出状态。

作者 - 图8


View

View 用于展示数据。ViewControllerCell 都可以看作是 ViewView 将用户输入绑定到 Action 的序列上,同时将页面状态绑定到 UI 组件上。

定义一个 View 只需要让它遵循 View 协议即可。然后你的类将自动获得一个 reactor 属性。这个属性应该在 View 的外面被设置:

  1. class ProfileViewController: UIViewController, View {
  2. var disposeBag = DisposeBag()
  3. }
  4. profileViewController.reactor = UserViewReactor() // 注入 reactor

reactor 属性被设置时,bind(reactor:) 方法就会被调用。执行这个方法来进行用户输入绑定和状态输出绑定。

  1. func bind(reactor: ProfileViewReactor) {
  2. // action (View -> Reactor)
  3. refreshButton.rx.tap.map { Reactor.Action.refresh }
  4. .bind(to: reactor.action)
  5. .disposed(by: self.disposeBag)
  6. // state (Reactor -> View)
  7. reactor.state.map { $0.isFollowing }
  8. .bind(to: followButton.rx.isSelected)
  9. .disposed(by: self.disposeBag)
  10. }

Reactor

Reactor 是与 UI 相互独立的一层,主要负责状态管理。Reactor 最重要的作用就是将业务逻辑从 View 中抽离。每一个 View 都有对应的 Reactor 并且将所有的逻辑代理给 ReactorReactor 不需要依赖 View,所以它很容易被测试。

遵循 Reactor 协议即可定义一个 Reactor。这个协议需要定义三个类型:ActionMutationState。它也需要一个 initialState 属性。

  1. class ProfileViewReactor: Reactor {
  2. // 代表用户行为
  3. enum Action {
  4. case refreshFollowingStatus(Int)
  5. case follow(Int)
  6. }
  7. // 代表附加作用
  8. enum Mutation {
  9. case setFollowing(Bool)
  10. }
  11. // 代表页面状态
  12. struct State {
  13. var isFollowing: Bool = false
  14. }
  15. let initialState: State = State()
  16. }

Action 代表用户行为,State 代表页面状态。MutationActionState 的桥梁。Reactor 通过两步将用户行为序列转换为页面状态序列mutate()reduce()

作者 - 图9

mutate()

mutate() 接收一个 Action ,然后创建一个 Observable<Mutation>

  1. func mutate(action: Action) -> Observable<Mutation>

每种附加作用,如,异步操作,API 调用都是在这个方法内执行。

  1. func mutate(action: Action) -> Observable<Mutation> {
  2. switch action {
  3. case let .refreshFollowingStatus(userID): // receive an action
  4. return UserAPI.isFollowing(userID) // create an API stream
  5. .map { (isFollowing: Bool) -> Mutation in
  6. return Mutation.setFollowing(isFollowing) // convert to Mutation stream
  7. }
  8. case let .follow(userID):
  9. return UserAPI.follow()
  10. .map { _ -> Mutation in
  11. return Mutation.setFollowing(true)
  12. }
  13. }
  14. }

reduce()

reduce() 通过旧的 State 以及 Mutation 创建一个新的 State

  1. func reduce(state: State, mutation: Mutation) -> State

这个方法是一个纯函数。它将同步的返回一个 State。不会产生其他的作用。

  1. func reduce(state: State, mutation: Mutation) -> State {
  2. var state = state // create a copy of the old state
  3. switch mutation {
  4. case let .setFollowing(isFollowing):
  5. state.isFollowing = isFollowing // manipulate the state, creating a new state
  6. return state // return the new state
  7. }
  8. }

transform()

transform() 转换每一种序列。有三种转换方法:

  1. func transform(action: Observable<Action>) -> Observable<Action>
  2. func transform(mutation: Observable<Mutation>) -> Observable<Mutation>
  3. func transform(state: Observable<State>) -> Observable<State>

执行这些方法可以转换或者组合其他的序列。例如,transform(mutation:) 最适合用来组合一个全局事件,生成一个 Mutation 序列。

它也可用来做调试:

  1. func transform(action: Observable<Action>) -> Observable<Action> {
  2. return action.debug("action") // Use RxSwift's debug() operator
  3. }

示例

下一节将用 Github Search 来演示如何使用 ReactorKit