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

为何使用.sheet调用含EnvironmentObject的View崩溃,NavigationLink却正常?

问题

在SwiftUI开发中,使用.sheet展示依赖EnvironmentObject的Inputview时,应用崩溃并抛出错误:

Fatal error: No ObservableObject of type Blabla found. A View.environmentObject(_:) for Blabla may be missing as an ancestor of this view.

但使用NavigationLink结合NavigationStack打开该视图时,应用却能正常运行。多次尝试用.sheet结合EnvironmentObject编写小型应用,始终遇到该错误,改用NavigationLink后问题解决。相关代码如下:

ContentView 代码

struct ContentView: View {
    
    @State var showInputView = false
    @StateObject var myCars = Cars(autos: [Car( type: "Mercedes"), Car(type: "Porsche"), Car( type: "Audi")])

    var body: some View {
        NavigationStack{
            VStack {
                List(myCars.cars, id: \.id){car in
                    Text(car.type)
                }

                NavigationLink {
                    Inputview()
                } label: {
                    Text("Show Input View")
                }
                Button("Button InputView"){
                    showInputView = true
                }
                .sheet(isPresented: $showInputView){
                    Inputview()
                }
            }
        }
        .environmentObject(myCars)
        .sheet(isPresented: $showInputView){
            Inputview()
        }
        .padding()
    }
        
}

Inputview 代码

struct Inputview: View {
    @EnvironmentObject var cars: Cars
    var body: some View {
        VStack{
            List(cars.cars, id: \.id){auto in
                Text(auto.type)}

            
        }
    }
}

原因分析

  • NavigationStack属于当前视图树的一部分,你把.environmentObject(myCars)添加到了NavigationStack的外部,所以NavigationLink跳转的Inputview会自动继承这个环境对象——因为它是NavigationStack的子视图,属于同一层级链。
  • 而.sheet弹出的是模态视图,它的视图层级完全独立于当前的视图树,不会自动继承父视图的环境对象。你代码里的两个.sheet都直接实例化了Inputview(),没有给它注入对应的EnvironmentObject,所以运行时会找不到对象导致崩溃。

另外你代码里绑定了两个.sheet到同一个showInputView变量,点击按钮时会弹出两个模态框,这也是需要修复的冗余代码。

解决方案

当然可以用.sheet结合EnvironmentObject,只需要给模态视图明确注入环境对象即可,有两种常见方式:

方式一:直接给.sheet内的视图添加环境对象

修改.sheet的代码,给Inputview加上.environmentObject(myCars):

.sheet(isPresented: $showInputView){
    Inputview()
        .environmentObject(myCars)
}

这种方式最直观,明确给独立的模态视图注入所需的环境对象。

方式二:将环境对象注入到更高层级(可选)

如果你有多个模态视图都需要用到同一个环境对象,可以把.environmentObject(myCars)添加到整个ContentView的最外层,比如:

var body: some View {
    NavigationStack{
        // ... 原有内容
    }
    .padding()
    .environmentObject(myCars) // 移到最外层
}

不过因为模态视图的独立性,更推荐方式一,让依赖关系更清晰。

最后记得删除重复的.sheet绑定,只保留一个即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 06:05:26