swift modal-dialog swiftui

SwiftUI despedir modal



modal-dialog (4)

Dado que SwiftUI es declarativo, no hay un método de dismiss . ¿Cómo se puede agregar un botón de cerrar / cerrar en DetailView ?

struct DetailView: View { var body: some View { Text("Detail") } } struct ContentView : View { var body: some View { PresentationButton(Text("Click to show"), destination: DetailView()) } }


Aquí hay una manera de descartar la vista presentada.

struct DetailView: View { @Binding var dismissFlag: Bool var body: some View { Group { Text("Detail") Button(action: { self.dismissFlag.toggle() }) { Text("Dismiss") } } } } struct ContentView : View { @State var dismissFlag = false var body: some View { Button(action: { self.dismissFlag.toggle() }) { Text("Show") } .presentation(!dismissFlag ? nil : Modal(DetailView(dismissFlag: $dismissFlag)) { print("dismissed") }) } }


Dado que PresentationButton es fácil de usar, pero oculta el estado que está socavando el carácter predictivo de SwiftUI lo he implementado con un Binding accesible.

public struct BindedPresentationButton<Label, Destination>: View where Label: View, Destination: View { /// The state of the modal presentation, either `visibile` or `off`. private var showModal: Binding<Bool> /// A `View` to use as the label of the button. public var label: Label /// A `View` to present. public var destination: Destination /// A closure to be invoked when the button is tapped. public var onTrigger: (() -> Void)? public init( showModal: Binding<Bool>, label: Label, destination: Destination, onTrigger: (() -> Void)? = nil ) { self.showModal = showModal self.label = label self.destination = destination self.onTrigger = onTrigger } public var body: some View { Button(action: toggleModal) { label } .presentation( !showModal.value ? nil : Modal( destination, onDismiss: { self.toggleModal() } ) ) } private func toggleModal() { showModal.value.toggle() onTrigger?() } }

Así es como se usa:

struct DetailView: View { @Binding var showModal: Bool var body: some View { Group { Text("Detail") Button(action: { self.showModal = false }) { Text("Dismiss") } } } } struct ContentView: View { @State var showModal = false var body: some View { BindedPresentationButton( showModal: $showModal, label: Text("Show"), destination: DetailView(showModal: $showModal) ) { print("dismissed") } } }


Otra forma de descartar el modal es mediante la variable de entorno isPresented , que es:

Un enlace a un valor booleano que indica si esta instancia es parte de una jerarquía actualmente presentada.

Todo lo que necesita hacer es establecer el valor de esta variable en false en su vista modal:

struct DetailView : View { @Environment(/.isPresented) var isPresented: Binding<Bool>? var body: some View { Group { Text("Detail view") Button(action: { self.isPresented?.value = false }) { Text("Dismiss") } } } } struct ContentView : View { var body: some View { PresentationButton(Text("Show modal"), destination: DetailView()) } }


Puedes implementar esto.

struct view: View { @Environment(/.isPresented) private var isPresented private func dismiss() { isPresented?.value = false } }