SwiftUI 关闭最后一个sheet时如何同时dismiss多层sheet回到初始调用视图
解决多层sheet连续关闭直接回到根视图的问题
实现思路
SwiftUI中每张sheet的presentationMode仅能控制当前层级sheet的关闭,因此你在PickDefinition中调用dismiss()只能关闭当前页,上层的AddWord sheet仍会保留。
要实现直接回到BookView,只需将BookView中控制第一个sheet显隐的addingWord状态以Binding的形式逐层传递到最底层的PickDefinition,将其置为false即可一次性关闭所有层级的sheet,直接回到根视图。
具体修改步骤
- 给
AddWord结构体新增showAddWord绑定属性,同时在BookView弹出AddWord时传入$addingWord - 给
PickDefinition结构体新增showAddWord绑定属性,同时在AddWord弹出PickDefinition时传入该绑定值 - 替换
PickDefinition中选中释义后的关闭逻辑,直接将showAddWord置为false即可
修改后完整代码
struct BookView: View { @ObservedObject var book: Book @State var addingWord = false @Environment(\.presentationMode) var presentationMode var body: some View { VStack { List(Array(zip(book.words, book.definitions)), id: \.self.0) { (word, definition) in Text("\(word) - \(definition)") } } .onAppear(perform: { DB_Manager().openBook(name: book.name, book: self.book) }) .navigationBarTitle("\(book.name)") .navigationBarItems(trailing: Button(action: { self.addingWord = true }) { Image(systemName: "plus") } ).sheet(isPresented: $addingWord) { // 传入binding值 AddWord(book: self.book, showAddWord: $addingWord) } } } struct AddWord: View { @ObservedObject var book: Book @StateObject var currentArray = SaveArray() @State var addingDefinition = false @State var word = "" @State var definition = "" @State var allDefinitions: [String] = [] // 新增绑定属性 @Binding var showAddWord: Bool @Environment(\.presentationMode) var presentationMode var body: some View { NavigationView { Form { TextField("Word: ", text: $word) } .navigationBarTitle("Add word") .navigationBarItems(trailing: Button("Add") { if self.word != "" { book.words.append(self.word) getDef(self.word, book, currentArray) addingDefinition = true } }).sheet(isPresented: $addingDefinition) { // 向下传递binding值 PickDefinition(definitions: currentArray, book: book, word: self.word, showAddWord: $showAddWord) } } } } struct PickDefinition: View { @ObservedObject var definitions: SaveArray var book: Book var word: String // 新增绑定属性 @Binding var showAddWord: Bool @Environment(\.presentationMode) var presentationMode var body: some View { NavigationView { VStack { List { ForEach(0 ..< definitions.currentArray.count, id: \.self) { index in Button("\(self.definitions.currentArray[index])", action: { print("hello") DB_Manager().addWords(name: self.book.name, word: self.word, definition: self.definitions.currentArray[index]) book.definitions.append(self.definitions.currentArray[index]) // 直接关闭所有层级sheet self.showAddWord = false }) } } } .navigationTitle("Choose") } } }
补充说明
如果你的项目最低支持iOS 15及以上版本,也可以使用@Environment(\.dismiss)替代presentationMode,逻辑和上述方案一致,只需将绑定的状态值传到最底层直接置false即可。
内容的提问来源于stack exchange,提问作者Nikolas Caceres
相关产品推荐
相关产品推荐

