I know this question has been asked and answered before. Not sure if this changed/broke in Beta 4 for SwiftUI, but I can't seem to get the isPresented solution to work to dismiss a modal shown with sheet.
Here is a simple example of what I tried, I thought this would work, but clicking "Close" does nothing and when I inspect self.isPresented?.value it's nil.
struct DetailView: View {
@Environment(\.isPresented) var isPresented: Binding<Bool>?
var body: some View {
Button(action: {
self.isPresented?.value = false
}) {
Text("Close")
}
}
}
struct ContentView: View {
@State private var showingModal = false
var body: some View {
Button(action: {
self.showingModal = true
}) {
Text("Show detail")
}.sheet(isPresented: $showingModal) {
DetailView()
}
}
}
Update based on suggestion, this works. Seems like too much book keeping to me, hope this gets updated.
struct DetailView: View {
@Binding var showingModal: Bool
var body: some View {
Button(action: {
self.showingModal = false
}) {
Text("Close")
}
}
}
struct ContentView: View {
@State private var showingModal = false
var body: some View {
Button(action: {
self.showingModal = true
}) {
Text("Show detail")
}.sheet(isPresented: $showingModal) {
DetailView(showingModal: self.$showingModal)
}
}
}
Beta 6
Use presentationMode from the @Environment.
struct SomeView: View {
@Environment(\.presentationMode) var presentationMode
var body: some View {
VStack {
Text("Ohay!")
Button("Close") {
self.presentationMode.wrappedValue.dismiss()
}
}
}
}
Another solution is to add a delegate property to your SwifUI view which passes the dismiss action back to the presenter.
protocol MySwiftUIViewDelegate: class {
func myDismissAction()
}
struct MySwiftUIView {
weak var delegate: MySwiftUIViewDelegate?
var body: some View {
Button("Dismiss") {
self.delegate?.myDismissAction()
}
}
}
class MyViewController: UIViewController, MySwiftUIViewDelegate {
func presentMyView() {
var myView = MySwiftUIView()
myView.delegate = self
let hostingViewController = UIHostingController(rootView: myView)
present(vc, animated: true, completion: nil)
}
// MARK: - MySwiftUIViewDelegate
func myDismissAction() {
dismiss(animated: true)
}
}
While this may seem a bit convoluted, it is also arguably better to make the presenter responsible for handling the dismissal, so that the view doesn't have to know how it was presented (e.g. push vs modal), thus making your code more modular. Plus you might want other delegated methods, depending on what you're working on, so you might have a delegate protocol already. And it gives you a convenient place to execute any additional code when the view is dismissed.
(Although keep in mind that depending on the modal presentation style / settings, users may also be able to dismiss by pulling the view down.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With