求基于新ReducerProtocol的Swift Composable Architecture最简共享状态实现示例
用ReducerProtocol实现TCA共享状态的最简示例
核心逻辑
TCA的共享状态不需要额外依赖ObservedObject注入,核心是将共享数据放在顶层全局状态中,通过Reducer的组合(Scope/pullback)让子Feature能访问或修改共享状态。以下是完整的最简实现:
1. 定义全局状态与动作
import ComposableArchitecture // 共享的用户模型(所有Feature依赖的数据) struct User: Equatable { var name: String var darkModeEnabled: Bool } // 全局状态:包含共享数据 + 各个子Feature的本地状态 struct AppState: Equatable { var user: User var profile: ProfileFeature.State var settings: SettingsFeature.State } // 全局动作:包含子Feature动作 + 修改共享状态的动作 enum AppAction: Equatable { case profile(ProfileFeature.Action) case settings(SettingsFeature.Action) case updateUserName(String) }
2. 实现子Feature的Reducer
个人资料Feature(修改用户名)
struct ProfileFeature: ReducerProtocol { // 子Feature无本地状态,用空结构体占位 struct State: Equatable {} enum Action: Equatable { case nameChanged(String) } func reduce(into state: inout State, action: Action) -> EffectTask<Action> { switch action { case .nameChanged(let newName): // 发送全局动作,通知顶层Reducer修改共享状态 return .send(AppAction.updateUserName(newName)) } } }
设置Feature(切换暗黑模式)
struct SettingsFeature: ReducerProtocol { struct State: Equatable {} enum Action: Equatable { case darkModeToggled(Bool) } func reduce(into state: inout State, action: Action) -> EffectTask<Action> { // 这里不需要额外逻辑,顶层Reducer会处理该动作并修改共享状态 return .none } }
3. 顶层Reducer组合与共享状态处理
struct AppReducer: ReducerProtocol { var body: some ReducerProtocol<AppState, AppAction> { // 将ProfileFeature与全局状态/动作关联 Scope(state: \.profile, action: /AppAction.profile) { ProfileFeature() } // 处理全局动作,修改共享状态 Reduce { state, action in switch action { case .settings(.darkModeToggled(let isEnabled)): state.user.darkModeEnabled = isEnabled return .none case .updateUserName(let newName): state.user.name = newName return .none default: return .none } } } }
4. SwiftUI视图实现
import SwiftUI // 个人资料视图:读取并修改共享用户名 struct ProfileView: View { let store: StoreOf<ProfileFeature> var body: some View { WithViewStore(store) { viewStore in TextField("用户名", text: viewStore.binding( get: { _ in store.environment.user.name }, send: ProfileFeature.Action.nameChanged )) .padding() } } } // 设置视图:读取并修改共享暗黑模式状态 struct SettingsView: View { let store: StoreOf<SettingsFeature> var body: some View { WithViewStore(store) { viewStore in Toggle("暗黑模式", isOn: viewStore.binding( get: { _ in store.environment.user.darkModeEnabled }, send: SettingsFeature.Action.darkModeToggled )) .padding() } } } // 主视图:持有全局Store,分发到子视图 struct MainView: View { let store: StoreOf<AppReducer> var body: some View { TabView { ProfileView(store: store.scope(state: \.profile, action: AppAction.profile)) .tabItem { Label("个人资料", systemImage: "person") } SettingsView(store: store.scope(state: \.settings, action: AppAction.settings)) .tabItem { Label("设置", systemImage: "gear") } } } } // 应用入口 @main struct SharedStateDemoApp: App { static let store = Store( initialState: AppState( user: User(name: "默认用户", darkModeEnabled: false), profile: ProfileFeature.State(), settings: SettingsFeature.State() ), reducer: AppReducer() ) var body: some Scene { WindowGroup { MainView(store: SharedStateDemoApp.store) } } }
关键要点
- 共享状态中心化:所有共享数据放在顶层
AppState,避免分散管理。 - Reducer组合:通过
Scope将子Feature的Reducer绑定到全局状态/动作,子Feature可以发送全局动作触发共享状态修改。 - 视图访问:子视图通过
scope从全局Store派生局部Store,通过绑定直接读取/修改共享状态。
内容的提问来源于stack exchange,提问作者Small Talk
相关产品推荐
相关产品推荐

