Swift 中的单向数据流 - 灵感来源于 Redux 和 NgRx。
基于 Combine - 非常适合与 SwiftUI 一起使用。
在开发应用程序时,跟踪数据的流动方向会变得非常困难。数据向多个方向流动,并且很容易因多个真实来源而变得不一致。
使用 Fluxor,数据仅沿一个方向流动,只有一个单一真实来源,状态的更新通过纯函数完成,应用程序中的流动方向可以很容易地被跟踪,并且所有单独的部分都可以单独进行单元测试。
Fluxor 由以下类型组成
Store
包含一个不可变的状态 (单一真实来源)。Action
来更新状态。Reducer
基于分发的 Actions 为 Store 提供一个新的状态。Selector
选择(并最终转换)状态的一部分以供使用(例如,在视图中)。Effect
由 Actions 触发,并且可以执行异步任务,这些任务又可以分发新的 Actions。Interceptor
拦截每个分发的 Action 和状态更改,以便更轻松地进行调试。可以使用 Swift Package Manager 将 Fluxor 作为依赖项安装到您的项目中,只需添加 https://github.com/FluxorOrg/Fluxor.git
。
至少,使用 Fluxor 的应用程序将需要一个 Store
、一个 Action
、一个 Reducer
、一个 Selector
和一个状态。
这是一个设置示例,其中触发 IncrementAction
(1) 将增加 AppState
(3) 中的 counter
(2),并且当使用 counterSelector
(4) 在 Store
上进行选择时,每次状态更改时都会发布 counter
(5)。
import Combine
import Fluxor
import Foundation
// 3
struct AppState {
var counter: Int
}
// 1
struct IncrementAction: Action {
let increment: Int
}
// 4
let counterSelector = Selector(keyPath: \AppState.counter)
let store = Store(initialState: AppState(counter: 0))
store.register(reducer: Reducer(
ReduceOn(IncrementAction.self) { state, action in
state.counter += action.increment // 2
}
))
let cancellable = store.select(counterSelector).sink {
print("Current count: \($0)") // 5
}
store.dispatch(action: IncrementAction(increment: 42))
// Will print out "Current count: 42"
上面的示例是一个简单的用例,其中一个 Action
被分发,并且状态被一个 Reducer
更新。在应该在分发 Action
时发生某些事情(例如,从互联网或某些系统服务中获取数据)的情况下,Fluxor 提供了 Effects
。
Effects
在 Store
中注册,并且将接收所有分发的 Action
。在大多数情况下,Effect
将是一个从分发的 Action
映射的 Publisher
- 映射的 Action
将在 Store
上分发。
或者,当 Effect
不需要分发 Action
时,它也可以是一个 Cancellable
。
import Combine
import Fluxor
import Foundation
class TodosEffects: Effects {
typealias Environment = AppEnvironment
let fetchTodos = Effect<Environment>.dispatchingOne { actions, environment in
actions.ofType(FetchTodosAction.self)
.flatMap { _ in
environment.todoService.fetchTodos()
.map { DidFetchTodosAction(todos: $0) }
.catch { _ in Just(DidFailFetchingTodosAction(error: "An error occurred.")) }
}
.eraseToAnyPublisher()
}
}
如果需要对所有分发的 Action
和状态更改进行只读访问,则可以使用 Interceptor
。 Interceptor
只是一个协议,当在 Store
中注册时,符合此协议的类型的实例将在每次分发 Action
时收到回调。
Fluxor 带有两个 Interceptor
的实现
PrintInterceptor
用于将 Action
和状态更改打印到日志。TestInterceptor
用于帮助断言在单元测试中分发了特定的 Action
。Fluxor 附带了软件包,使其更容易与 SwiftUI 一起使用以及用于测试使用 Fluxor 的应用程序。
Fluxor 有一个配套应用程序,FluxorExplorer,它有助于在使用 Fluxor 调试应用程序时。 FluxorExplorer 允许您查看分发的 Action
和状态更改,以调试应用程序的数据流。
FluxorExplorer 在 App Store 上可用,也可以作为开源提供。
要了解更多关于如何使用 FluxorExplorer 的信息,请转到该应用程序的存储库。