Redux-like 状态容器在 SwiftUI 中的应用教程
项目介绍
本项目旨在通过 SwiftUI 实现类似 Redux 的状态管理模式,提供单一数据源(Single Source of Truth),使得应用状态管理更加清晰和易于调试。项目灵感来源于 Redux、Elm 和 The Composable Architecture (TCA),并结合了 Swift 的并发模型。
项目快速启动
环境要求
- Xcode 12 或更高版本
- Swift 5.3 或更高版本
安装步骤
-
克隆项目仓库:
git clone https://github.com/mecid/redux-like-state-container-in-swiftui.git
-
打开项目文件夹:
cd redux-like-state-container-in-swiftui
-
打开 Xcode 项目文件:
open ReduxLikeStateContainer.xcodeproj
-
在 Xcode 中选择合适的模拟器或连接的设备,然后运行项目。
示例代码
以下是一个简单的示例,展示如何在 SwiftUI 中使用 Redux-like 状态容器:
import SwiftUI
import Combine
// 定义状态
struct AppState {
var counter: Int = 0
}
// 定义动作
enum AppAction {
case increment
case decrement
}
// 定义环境
struct AppEnvironment {
var mainQueue: AnySchedulerOf<DispatchQueue> = .main
}
// 定义 Reducer
typealias AppReducer = Reducer<AppState, AppAction, AppEnvironment>
let appReducer: AppReducer = { state, action, environment in
switch action {
case .increment:
state.counter += 1
return Empty(completeImmediately: true).eraseToAnyPublisher()
case .decrement:
state.counter -= 1
return Empty(completeImmediately: true).eraseToAnyPublisher()
}
}
// 定义 Store
final class Store<State, Action, Environment>: ObservableObject {
@Published private(set) var state: State
private let environment: Environment
private let reducer: AppReducer
private var effectCancellables: Set<AnyCancellable> = []
init(initialState: State, reducer: @escaping AppReducer, environment: Environment) {
self.state = initialState
self.reducer = reducer
self.environment = environment
}
func send(_ action: Action) {
let effects = self.reducer(&self.state, action, self.environment)
effects.sink(receiveValue: { [weak self] in self?.send($0) })
.store(in: &self.effectCancellables)
}
}
// 定义视图
struct ContentView: View {
@ObservedObject private var store: Store<AppState, AppAction, AppEnvironment>
init(store: Store<AppState, AppAction, AppEnvironment>) {
self.store = store
}
var body: some View {
VStack {
Text("Counter: \(store.state.counter)")
.padding()
Button("Increment") {
store.send(.increment)
}
Button("Decrement") {
store.send(.decrement)
}
}
}
}
// 应用入口
@main
struct ReduxLikeStateContainerApp: App {
let store = Store(initialState: AppState(), reducer: appReducer, environment: AppEnvironment())
var body: some Scene {
WindowGroup {
ContentView(store: store)
}
}
}
应用案例和最佳实践
应用案例
- 计数器应用:如上示例代码所示,通过 Redux-like 状态容器管理计数器的状态。
- Todo 列表应用:使用 Redux-like 状态容器管理 Todo 列表的添加、删除和完成状态。
最佳实践
- 单一数据源:确保应用状态集中管理,避免状态分散导致的 bug。
- 纯函数 Reducer:Reducer 应该是纯函数,不产生