Swift Composable Architecture中如何实现多Sheet视图的展示?
关于Composable Architecture中Sheet多视图展示的问题
我正在学习Swift与Composable Architecture,目前跟随官方多目的地教程学习。现有代码运行正常,但在同一个Sheet中展示不同视图时遇到问题。我已在LoginView中新增了如下Destination定义:
struct LoginFeature: Reducer { ... ... var body: some ReducerOf<Self> { Reduce { state, action in switch action { case .forgotPasswordButtonTapped: state.destination = .forgotPassword( ForgotPasswordFeature.State() ) return .none case .privacyPolicyButtonTapped: state.destination = .privacyPolicy( GeneralWebFeature.State(urlString: "<some link>") ) return .none ... ... }
以及Destination的Reducer扩展:
extension LoginFeature { struct Destination: Reducer { enum State: Equatable { case forgotPassword(ForgotPasswordFeature.State) case privacyPolicy(GeneralWebFeature.State) } enum Action: Equatable { case forgotPassword(ForgotPasswordFeature.Action) case privacyPolicy(GeneralWebFeature.Action) } var body: some ReducerOf<Self> { Scope(state: /State.forgotPassword, action: /Action.forgotPassword) { ForgotPasswordFeature() } Scope(state: /State.privacyPolicy, action: /Action.privacyPolicy) { GeneralWebFeature() } } } }
目前我的Sheet代码仅支持单一视图(忘记密码),想修改为支持同时展示忘记密码和隐私政策两个视图,当前代码如下:
.sheet( store: self.store.scope( state: \.$destination, action: { .destination($0) } ), state: /LoginFeature.Destination.State.forgotPassword, action: LoginFeature.Destination.Action.forgotPassword ) { forgotPasswordStore in NavigationStack { ForgotPasswordView(store: forgotPasswordStore) } }
解决方案
要支持多视图Sheet,你需要为每个目的地分别添加对应的.sheet修饰符,这是TCA官方推荐的清晰写法:
// 忘记密码对应的Sheet .sheet( store: self.store.scope( state: \.$destination, action: { .destination($0) } ), state: /LoginFeature.Destination.State.forgotPassword, action: LoginFeature.Destination.Action.forgotPassword ) { forgotPasswordStore in NavigationStack { ForgotPasswordView(store: forgotPasswordStore) } } // 隐私政策对应的Sheet .sheet( store: self.store.scope( state: \.$destination, action: { .destination($0) } ), state: /LoginFeature.Destination.State.privacyPolicy, action: LoginFeature.Destination.Action.privacyPolicy ) { privacyPolicyStore in NavigationStack { GeneralWebView(store: privacyPolicyStore) } }
说明
每个.sheet对应一个目的地的状态和动作:
- 当
state.destination被设置为.forgotPassword时,忘记密码的Sheet会弹出; - 当
state.destination被设置为.privacyPolicy时,隐私政策的Sheet会弹出。
这种方式符合TCA的单向数据流理念,每个目的地的状态和动作都被清晰隔离,后续扩展更多目的地时只需添加新的.sheet即可。
内容的提问来源于stack exchange,提问作者Hussain
相关产品推荐
相关产品推荐

