SwiftUI中Sheet无法关闭求助:dismiss及presentationMode均无效
问题原因与解决办法
你遇到的问题核心是环境变量的作用域问题:你在ContentView中声明了@Environment(\.dismiss)和@Environment(\.presentationMode),但直接在.sheet的尾随闭包里使用这些变量时,它们指向的是ContentView的上下文,而非弹出的Sheet自身的上下文,所以调用dismiss()或presentationMode.wrappedValue.dismiss()无法关闭Sheet。
正确的实现方式
将Sheet中的内容抽成独立的View组件,在这个子View中单独声明环境变量,这样就能获取到Sheet自身的上下文环境,调用关闭方法才会生效:
struct ContentView: View { @State var sheetState = false @State private var value = "" var body: some View { VStack { Text(value) Button("Present Sheet") { sheetState.toggle() } } .sheet(isPresented: $sheetState) { // 使用独立的Sheet内容视图 SheetContentView(value: $value) } } } // 单独封装Sheet的内容视图 struct SheetContentView: View { @Binding var value: String // 在子View中声明环境变量,获取Sheet的上下文 @Environment(\.dismiss) private var dismiss var body: some View { Button("set1") { value = "1" dismiss() // 此时调用的是Sheet自身的关闭方法 } } }
如果仍想使用@Environment(\.presentationMode),也可以在子View中声明:
struct SheetContentView: View { @Binding var value: String @Environment(\.presentationMode) private var presentationMode var body: some View { Button("set1") { value = "1" presentationMode.wrappedValue.dismiss() } } }
额外说明
另外,如果你不想抽离子View,也可以通过在.sheet的闭包内给视图添加.environment(\.dismiss, dismiss)手动传递,但这种方式不够优雅,抽离子View是SwiftUI的标准做法,更符合视图分离的设计原则。
内容的提问来源于stack exchange,提问作者Martin Q
相关产品推荐
相关产品推荐

