SwiftUI中fullScreenCover关闭后如何执行后续视图跳转逻辑?
SwiftUI中dismiss全屏覆盖视图后执行后续逻辑的正确方式
在SwiftUI里使用fullScreenCover展示全屏弹窗时,若调用dismiss()后立即触发新视图的展示(比如通过通知),会抛出[Presentation] Attempt to present xxx from yyy which is already presenting zzz错误。这是因为dismiss()是异步操作,弹窗还未完全关闭就发起新的present请求,导致冲突。
UIKit的dismiss方法支持通过completion回调在弹窗关闭后执行逻辑,SwiftUI中可以通过以下两种原生方式实现相同效果,避免使用不可靠的延迟方案:
方法一:利用视图的onDisappear回调
将后续逻辑放到弹窗视图的onDisappear中,确保视图真正消失后再执行操作。如果需要区分是按钮触发的关闭还是其他原因(比如系统返回),可以添加标记变量:
struct FullScreenCoverView: View { @Environment(\.dismiss) var dismiss @State private var isButtonTriggeredDismiss = false var body: some View { Button("This is a test") { isButtonTriggeredDismiss = true dismiss() } .onDisappear { // 仅在按钮触发关闭时执行逻辑 if isButtonTriggeredDismiss { NotificationCenter.default.post(name: NSNotification.showNewScreen, object: nil) } } } }
方法二:监听弹窗的展示状态变化
通过@Environment(\.presentationMode)监听弹窗的展示状态,当状态变为未展示时执行后续逻辑:
struct FullScreenCoverView: View { @Environment(\.dismiss) var dismiss @Environment(\.presentationMode) var presentationMode var body: some View { Button("This is a test") { dismiss() } .onChange(of: presentationMode.wrappedValue.isPresented) { isPresented in if !isPresented { NotificationCenter.default.post(name: NSNotification.showNewScreen, object: nil) } } } }
这两种方法都能确保在弹窗完全关闭后再发起新的视图展示请求,不会出现冲突报错,比固定延迟的方案更可靠。
内容的提问来源于stack exchange,提问作者Buyin Brian
相关产品推荐
相关产品推荐

