SwiftUI使用.sheet时触发EXC_BAD_ACCESS崩溃该如何解决?
SwiftUI .sheet修饰器触发EXC_BAD_ACCESS崩溃的原因及解决方案
问题原因
这是iOS 15.0 ~ iOS 15.3版本中存在的SwiftUI底层已知Bug,触发核心是视图生命周期与状态更新的时序冲突:你在根视图的onAppear回调中同步修改了控制sheet显隐的@State变量,此时根视图还未完全挂载到应用的视图层级上,sheet尝试附着到未完成初始化的宿主视图时,就会触发野指针访问,抛出EXC_BAD_ACCESS崩溃。同时你当前使用的带空onDismiss参数的sheet重载方法,也会提升该Bug的触发概率。
解决方案
可根据你的项目兼容需求选择对应方案:
- 方案1:调整状态更新时序,不要在
onAppear中同步修改控制sheet的状态变量,将状态变更逻辑丢到主队列的下一个运行循环执行,保证根视图完成挂载后再触发sheet展示,同时去掉不必要的空onDismiss闭包,使用仅带isPresented和content参数的sheet重载,参考代码如下:
@main struct No_EmotionApp: App { @State private var showing_add = false var body: some Scene { WindowGroup { Text("") .sheet(isPresented: $showing_add) { Text("") } .onAppear{ DispatchQueue.main.async { showing_add.toggle() } } } } }
- 方案2:如果需要兼容更低版本系统,可将sheet的挂载位置移到更稳定的上层容器视图(比如ZStack、NavigationStack)上,同时将控制显隐的状态变量放到
ObservableObject类型的视图模型中管理,避免根视图@State刷新带来的渲染时序问题。 - 方案3:若应用最低兼容版本可升级到iOS 15.4及以上,该Bug已在后续系统版本的SwiftUI底层修复,无需额外修改逻辑即可正常运行。
内容的提问来源于stack exchange,提问作者Mikhail Safir
相关产品推荐
相关产品推荐

