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

提取包含Observable Object的SwiftUI子视图后Sheet无法关闭的问题排查

包含Observable Object的SwiftUI子视图后Sheet无法关闭的问题排查

嘿,这个问题我之前也踩过坑,核心原因其实特别好理解——你在ExtractedView里重新创建了一个完全独立的ApplicationData实例!

咱们拆解下问题逻辑:

  • 你的ContentView里初始化了一个appData,Sheet的显示/隐藏完全由这个实例的isShowingSheet状态控制
  • 当你把Sheet内容提取到ExtractedView后,子视图里又写了@Bindable var appData = ApplicationData(),这等于生成了一个和父视图毫无关联的新对象
  • 所以点击子视图里的Dismiss按钮时,你修改的是这个新对象的isShowingSheet值,而真正控制Sheet显示的父视图实例根本没收到变化,Sheet自然不会关闭

那怎么解决呢?只需要让子视图复用父视图的appData实例就行,不要在子视图里重新初始化:

第一步:修改子视图定义,接收外部传入的实例

struct ExtractedView: View {
    @Bindable var appData: ApplicationData // 去掉默认初始化,改为外部传入
    
    var body: some View {
        VStack{
            Text("Brewing Database")
                .font(.title)
                .padding(32)
            Text("Showing sheet")
                .padding(16)
            Button("Dismiss", action: {appData.isShowingSheet.toggle()})
        }
    }
}

第二步:在父视图中传递自己的appData给子视图

.sheet(isPresented: $appData.isShowingSheet, onDismiss: didDismiss) {
    ExtractedView(appData: appData) // 把父视图的实例传进去
}

这样修改后,子视图和父视图共享的是同一个ApplicationData实例,点击Dismiss按钮修改的就是控制Sheet显示的那个isShowingSheet状态,Sheet就能正常关闭啦。

另外提个小建议:如果这个ApplicationData需要在多个视图间共享,你可以在ContentView里用@State来初始化它(比如@State private var appData = ApplicationData()),这样能保证实例的生命周期和视图绑定得更稳妥,不过你现在用Observation框架的@Observable配合@Bindable传递实例的方式已经完全没问题了。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.08 14:23:02