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

如何在NavigationStack的不同视图间共享同一EnvironmentObject实例

如何让所有页面共享同一个UserDataProvider实例?

你现在的问题是只有firstPage分支创建并注入了UserDataProvider实例,后续的secondPage和thirdPage无法复用这个实例。可以通过以下几种方式解决:

方法一:在路由类中持有实例引用

  1. 首先在你的ManifestRouter类里添加一个可选属性来存储UserDataProvider:
class ManifestRouter: ObservableObject {
    // 保留你原有的其他属性和逻辑
    var userDataProvider: UserDataProvider?
}
  1. 在firstPage分支初始化实例时,同时赋值给路由类的属性:
case let .firstPage(traveler, user, cabin):
    let provider = UserDataProvider(traveler: traveler, user: user)
    manifestRouter.userDataProvider = provider
    ManifestFirstPage(manifestRouter: manifestRouter, cabin: cabin)
        .navigationBarHidden(true)
        .environmentObject(provider)
  1. 在其他页面分支中,复用路由类中已存储的实例:
case let .secondPage(cabin):
    guard let provider = manifestRouter.userDataProvider else {
        // 处理未初始化的情况,比如返回带默认实例的页面,或者提示错误
        return ManifestSecondPage(manifestRouter: manifestRouter, cabin: cabin)
            .navigationBarHidden(true)
            .environmentObject(UserDataProvider(traveler: Traveler(), user: User()))
    }
    ManifestSecondPage(manifestRouter: manifestRouter, cabin: cabin)
        .navigationBarHidden(true)
        .environmentObject(provider)

case let .thirdPage(cabin):
    guard let provider = manifestRouter.userDataProvider else {
        return ManifestThirdPage(manifestRouter: manifestRouter, cabin: cabin)
            .navigationBarHidden(true)
            .environmentObject(UserDataProvider(traveler: Traveler(), user: User()))
    }
    ManifestThirdPage(manifestRouter: manifestRouter, cabin: cabin)
        .navigationBarHidden(true)
        .environmentObject(provider)

方法二:在父视图中管理实例状态

如果这个view(for:)方法属于某个父视图(比如自定义的路由容器视图),可以在父视图中用@State或@ObservedObject持有UserDataProvider,这样所有子视图都能继承环境对象:

struct RouterContainerView: View {
    @ObservedObject var manifestRouter: ManifestRouter
    @State private var userDataProvider: UserDataProvider?
    
    var body: some View {
        view(for: manifestRouter.currentRoute)
            .environmentObject(userDataProvider ?? UserDataProvider(traveler: Traveler(), user: User()))
    }
    
    @ViewBuilder func view(for route: ManifestRouter.Route) -> some View {
        switch route {
        case let .firstPage(traveler, user, cabin):
            let provider = UserDataProvider(traveler: traveler, user: user)
            self.userDataProvider = provider
            ManifestFirstPage(manifestRouter: manifestRouter, cabin: cabin)
                .navigationBarHidden(true)
        case let .secondPage(cabin):
            ManifestSecondPage(manifestRouter: manifestRouter, cabin: cabin)
                .navigationBarHidden(true)
        case let .thirdPage(cabin):
            ManifestThirdPage(manifestRouter: manifestRouter, cabin: cabin)
                .navigationBarHidden(true)
        }
    }
}

这种方式下,只要父视图注入了环境对象,所有子页面(包括secondPage、thirdPage)只要在内部声明@EnvironmentObject var userDataProvider: UserDataProvider就能直接使用,不需要再单独注入。

注意事项

  • 确保所有需要使用UserDataProvider的页面都添加了@EnvironmentObject属性来接收实例。
  • 处理未经过firstPage直接进入其他页面的场景,避免出现nil崩溃,可以提供默认实例或者做路由拦截。

内容的提问来源于stack exchange,提问作者dennis

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 19:46:10