Elementary 是一个实验性的、单向的和纯函数式的 Swift 架构。它的灵感来源于 ELM 和 Redux。其背后的主要动机是 SwiftUI 的引入,但这个核心包不依赖于 Combine 或 SwiftUI。
当使用 Swift 包管理器时,请使用 Xcode 11+ 安装,或将以下行添加到您的依赖项中
.package(url: "https://github.com/mkj-is/Elementary.git", from: "0.1.0")
用于构建 SwiftUI 应用的基础扩展是 ElementaryCombine。如果您仅支持最新的 Apple 操作系统,请毫不犹豫地使用这个扩展。
另一个真正实验性的扩展是 ElementaryEffectBuilder。这个扩展用于使用新的 Swift 函数构建器组合副作用。
所有内容都通过使用以下组件初始化 Store
绑定在一起
让我们来看第一个例子:一个计数器的简单实现,用户可以对其进行递增、递减和重置。
首先,我们需要定义所有的 actions。在这种情况下,一些枚举就足够了
enum CounterAction {
case increment, decrement, reset
}
然后我们实现接受 state 和 action 并更新 state 的函数。这里唯一应该发生的事情是改变 state。
func updateCounter(state: inout Int, action: CounterAction) {
switch action {
case .increment:
state += 1
case .decrement:
state = max(0, state - 1)
case .reset:
state = 0
}
}
我们最后需要做的是初始化 store。这段代码正是这样做的,并模拟了应用程序的示例运行。可测试性是这种分解的关键特性之一,您可以在示例test cases中亲自查看。
let store = Store(state: 0, update: updateCounter)
store.dispatch(.increment)
store.dispatch(.increment)
store.dispatch(.decrement)
store.dispatch(.increment)
store.dispatch(.reset)
store.state
大多数客户端应用程序需要执行一些异步工作。让我们以简单的秒表为例,它每秒递增 state。
enum StopwatchAction {
case start, stop, increment, reset
}
func updateStopwatch(state: inout Int, action: StopwatchAction) {
switch action {
case .reset:
state = 0
case .increment:
state += 1
case .start, .stop:
break
}
}
现在我们已经定义了所有的 actions 和 update function。下一步是编写一个函数,该函数返回带有 timer 捕获值的新副作用。该 effect 将仅对两个 actions 做出反应:start 和 stop。当这些 actions 被 dispatch 时,timer 将被启动或停止。DispatchSourceTimer
用于使此代码具有多平台和向后兼容性。
func createStopwatchEffect() -> Effect<Int, StopwatchAction> {
var timer: DispatchSourceTimer?
return { _, action, dispatch in
switch action {
case .start:
timer = DispatchSource.makeTimerSource()
timer?.schedule(deadline: .now() + 1, repeating: 1)
timer?.setEventHandler {
dispatch(.increment)
}
timer?.resume()
case .stop, .reset:
timer = nil
case .increment:
break
}
}
}
欢迎所有贡献。
项目由 Matěj Kašpar Jirásek 创建。
项目根据 MIT license 获得许可。