SwiftUI中如何通过代码关闭Popover?现有代码存在异常
解决SwiftUI Popover通过Cancel按钮关闭异常的方法
我明白你遇到的问题了——直接通过绑定showSheet变量来关闭Popover,有时候会因为SwiftUI的视图刷新逻辑出现异常表现。这里有两个更可靠的方案,帮你顺畅关闭Popover:
方案1:使用@Environment(\.dismiss)(推荐,iOS 15+/macOS 12+)
这是苹果官方推荐的关闭模态视图的方式,不需要手动维护状态变量,直接通过环境提供的dismiss方法就能关闭Popover,代码更简洁也更稳定。
修改后的完整代码如下:
import SwiftUI struct ContentView: View { let lines = ["line 1", "line 2","line 3"] var body: some View { List { ForEach(lines, id: \.self) { Line(text: $0) } } } } struct Line: View { let text: String // 这里不需要@State,text是父视图传入的常量 @State private var showSheet = false var body: some View { Text(text) .onTapGesture { showSheet = true } .popover( isPresented: $showSheet, arrowEdge: .trailing ) { Pop() // 无需再传递绑定变量 } } } struct Pop: View { // 引入环境中的dismiss方法 @Environment(\.dismiss) private var dismiss var body: some View { VStack { Text("Option 1") Text("Option 2") Button("Cancel") { // 直接调用dismiss关闭Popover dismiss() } } .padding() } }
方案2:确保状态更新在主队列(兼容旧版本)
如果你需要兼容iOS 15之前的版本,可以在设置showSheet为false时,强制在主队列执行更新——部分异常是因为状态更新在非主线程导致的:
修改Pop结构体的Cancel按钮代码即可:
Button("Cancel") { DispatchQueue.main.async { self.showSheet = false } }
原代码的小优化点
另外提一句:原代码里Line结构体的text用了@State,但text是从父视图传入的常量,不需要用@State修饰,改成普通常量即可,避免不必要的状态更新干扰视图逻辑。
内容的提问来源于stack exchange,提问作者mica
相关产品推荐
相关产品推荐

