SwiftUI关闭sheet后立即弹出fullScreenCover显示为sheet的原因是什么
SwiftUI 关闭sheet后立即弹出fullScreenCover异常问题解答
问题根因
- SwiftUI的模态展示逻辑依赖当前视图的层级上下文,当你在同一个Runloop周期内同时修改
sheet = false和cover = true时,两个状态变更会被合并到同一个渲染事务中批量处理 - 此时系统尚未完成sheet的 dismiss 流程,会错误地将还未完全消失的sheet作为presenting宿主来弹出fullScreenCover,sheet本身的模态展示样式会被后续弹出的页面继承,最终导致fullScreenCover无法全屏展示
- 该问题在iOS 14版本的SwiftUI中尤为明显,这是因为iOS 14的SwiftUI模态栈状态同步逻辑存在缺陷,不会等待前一个模态的dismiss事务完全执行完成,就会处理后续的模态present请求
无延迟正确解决方案
不需要手动加固定延迟,使用sheet修饰符自带的onDismiss回调即可,该回调会在sheet完全关闭、视图层级恢复到父级之后自动触发,时机完全精准且无额外延迟:
struct ContentView: View { @State var sheet = false @State var cover = false // 新增标志位,标记sheet关闭后是否需要弹出fullScreenCover @State private var shouldShowCoverAfterDismiss = false var body: some View { Button("Click me for sheet") { sheet = true } .fullScreenCover(isPresented: $cover) { Text("This is a full screen cover") } // 给sheet添加onDismiss回调 .sheet(isPresented: $sheet, onDismiss: { if shouldShowCoverAfterDismiss { cover = true shouldShowCoverAfterDismiss = false } }) { Text("This is a sheet") Button("现在可以正常工作,无延迟") { shouldShowCoverAfterDismiss = true sheet = false } } } }
该方案兼容iOS 14及更高版本,是当前场景下最稳妥的处理方式。
内容的提问来源于stack exchange,提问作者Jerry B. no.1 intern
相关产品推荐
相关产品推荐

