You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 10:33:27