关闭工作表SwiftUI

时间:2019-07-27 14:55:19

标签: swiftui

我正尝试为我的模态表实现一个关闭按钮,如下所示:

struct TestView: View {
    @Environment(\.isPresented) var present
    var body: some View {
        Button("return") {
            self.present?.value = false
        }
    }
}

struct DataTest : View {
    @State var showModal: Bool = false

    var modal: some View {
        TestView()
    }
    var body: some View {
        Button("Present") {
            self.showModal = true
        }.sheet(isPresented: $showModal) {
            self.modal
        }
    }
}

但是,轻按返回键不会执行任何操作。显示模态时,控制台中将显示以下内容:

  

[WindowServer] display_timer_callback:意外状态(现在:5fbd2efe5da4 <预期:5fbd2ff58e89)

如果您强行打开present,您会发现它是nil

如何以编程方式关闭.sheet

4 个答案:

答案 0 :(得分:9)

使用presentationMode中的@Environment

  

测试版6

struct SomeView: View {
    @Environment(\.presentationMode) var presentationMode

    var body: some View {
        VStack {
            Text("Ohay!")
            Button("Close") {
                self.presentationMode.wrappedValue.dismiss()
            }
        }
    }
}

答案 1 :(得分:3)

Apple 建议(在 WWDC 2020 Data Essentials in SwiftUI 中)为此使用 @State@Binding。他们还将 isEditorPresented 布尔值和工作表的数据放在使用 @State 声明的同一个 EditorConfig 结构中,以便可以对其进行变异,如下所示:

import SwiftUI

struct Item: Identifiable {
    let id = UUID()
    let title: String
}

struct EditorConfig {
    var isEditorPresented = false
    var title = ""
    var needsSave = false
    
    mutating func present() {
        isEditorPresented = true
        title = ""
        needsSave = false
    }
    
    mutating func dismiss(save: Bool = false) {
        isEditorPresented = false
        needsSave = save
    }
}

struct ContentView: View {
    
    @State var items = [Item]()
    @State private var editorConfig = EditorConfig()
    
    var body: some View {
        NavigationView {
            Form {
                ForEach(items) { item in
                    Text(item.title)
                }
            }
            .navigationTitle("Items")
            .toolbar {
                ToolbarItem(placement: .primaryAction) {
                    Button(action: presentEditor) {
                        Label("Add Item", systemImage: "plus")
                    }
                }
            }
            .sheet(isPresented: $editorConfig.isEditorPresented, onDismiss: {
                if(editorConfig.needsSave) {
                    items.append(Item(title: editorConfig.title))
                }
            }) {
                EditorView(editorConfig: $editorConfig)
            }
        }
    }
    
    func presentEditor() {
        editorConfig.present()
    }
}

struct EditorView: View {
    @Binding var editorConfig: EditorConfig
    var body: some View {
        NavigationView {
            Form {
                TextField("Title", text:$editorConfig.title)
            }
            .toolbar {
                ToolbarItem(placement: .confirmationAction) {
                    Button(action: save) {
                        Text("Save")
                    }
                    .disabled(editorConfig.title.count == 0)
                }
                ToolbarItem(placement: .cancellationAction) {
                    Button(action: dismiss) {
                        Text("Dismiss")
                    }
                }
            }
        }
    }
    
    func save() {
        editorConfig.dismiss(save: true)
    }
    
    func dismiss() {
        editorConfig.dismiss()
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView(items: [Item(title: "Banana"), Item(title: "Orange")])
    }
}

答案 2 :(得分:2)

iOS 15

从 iOS 15 开始,我们可以使用可以作为 @Environment(\.dismiss) 访问的 DismissAction

不再需要使用 presentationMode.wrappedValue.dismiss()

struct SheetView: View {
    @Environment(\.dismiss) var dismiss

    var body: some View {
        NavigationView {
            Text("Sheet")
                .toolbar {
                    Button("Done") {
                        dismiss()
                    }
                }
        }
    }
}

答案 3 :(得分:1)

对我来说,Beta 4违反了此方法-使用环境变量isPresented-使用关闭按钮。这是我现在要做的:

struct ContentView: View {
    @State var showingModal = false

    var body: some View {
        Button(action: {
           self.showingModal.toggle()
        }) {
           Text("Show Modal")
        }
        .sheet(
            isPresented: $showingModal,
            content: { ModalPopup(showingModal: self.$showingModal) }
        )
    }
}

在您的模式视图中:

struct ModalPopup : View {
    @Binding var showingModal:Bool

    var body: some View {
        Button(action: {
            self.showingModal = false
        }) {
            Text("Dismiss").frame(height: 60)
        }
    }
}