5

A similar question in the UIKit: How to dismiss UIAlertController when tap outside the UIAlertController?

I have a basic alert with a few buttons (cancel/delete style). I'd like to "dismiss" the alert by tapping outside of it, similarly to what would "cancel" button do:

struct ContentView: View {
    @State private var showingAlert = false

    var body: some View {
        Button("Show Alert") {
            showingAlert = true
        }
        .alert("Important message", isPresented: $showingAlert) {
            Button("First") { }
            Button("Second") { }
            Button("Third") { }
        }
    }
}

I tried adding onTapGesture handler, but it didn't help.

Richard Topchii
  • 7,075
  • 8
  • 48
  • 115
  • Pretty sure you're going to have to either implement a `UIViewControllerRepresentable` and use ideas from your linked answer, or use Introspect library to find the `UIAlertController` that SwiftUI makes. Introspect doesn't find .alert out of the box, so it might be tricky. – Steve M Feb 19 '22 at 18:38

1 Answers1

1

I am not sure if an alert is the right choice for what you want to achieve. Alerts are not intended to be used in that way you described and to dismiss an alert by tapping outside would feel awkward in regards to the user experience on iOS and is not encouraged by apple to do so. SwiftUI is intended to be used on multiple apple platforms like AppleWatch or AppleTV where you cannot simply tap outside of an alert. Therefore no such mechanisms like you described are implemented in SwiftUI.

A better approach would be to create your own view and use the ZStack. Then you can use the onTapGesture modifier on any clickable area to dismiss your view. Please check the example for a simplified example.

struct ContentView: View {
    @State private var showingAlert = false

    var body: some View {
        ZStack {
            // green area is clickable
            VStack {
                Spacer()
                HStack {
                    Spacer()
                    Button("Show Alert") {
                                showingAlert = true
                            }
                    Spacer()
                }
               
                Spacer()
            }
            .background(.green)
            .onTapGesture {
                self.showingAlert = false
            }
            
            if(showingAlert) {
                // your overlay to be designed by you. 
                VStack {
                    Text("alert")
                }
                .frame(width: 100, height: 100, alignment: .center)
                .background(.gray)
            }
        }
       
    }
}
Erwin Schens
  • 424
  • 2
  • 9