How to show alert in SwiftUI (iOS 15+)

DevTechie Inc
Jan 15, 2023

Starting iOS 15 and above, Alert has been moved into presentation modifiers area meaning it’s now an alert modifier rather than a struct.

In this article, we will explore alerts in SwiftUI for iOS 15+.

alert modifier is used to show an alert when we want the user to act in response to the state of the app.

To show an alert, we create a boolean state variable which determines if the alert should be visible or not.

@State private var showAlert = false
From there, we attach alert modifier passing State variable as isPresented parameter along with the buttons we want to show in the alert.

.alert("This is an alert", isPresented: $showAlert) { 
    Button("OK") {}
    Button("Not OK") {}
}
We launch the alert by toggling the State variable.

showAlert.toggle()
Complete code:

struct DevTechieAlertsExample: View {
    @State private var showAlert = false
    var body: some View {
        NavigationView {
            VStack {
                Text("Learn iOS with DevTechie")
                    .font(.largeTitle)
                    .foregroundColor(.white)
                    .padding()
                    .background(.orange, in: RoundedRectangle(cornerRadius: 20))
                Button {
                    showAlert.toggle()
                } label: {
                    Text("Show alert")
                }
                .alert("This is an alert", isPresented: $showAlert) {
                    Button("OK") {}
                    Button("Not OK") {}
                }
                
            }
        }
    }
}
Notice that we are passing empty action to the alert but alert dialog still manages to dismiss itself. Well that’s because its the default behavior for alert.

If we remove all the buttons and leave alert modifier body empty, alert will still display OK button by default.

alert("This is an alert", isPresented: $showAlert) {}
We can add up-to 10 buttons in alert modifier:

.alert("This is an alert", isPresented: $showAlert) {
    Button("OK") {}
    Button("Not OK") {}
    Button("Hmm OK") {}
    Button("Well OOOK") {}
    Button("But wait") {}
    Button("Can I say something?") {}
    Button("Why close") {}
    Button("Only if you want to close") {}
    Button("Think again") {}
    Button("OK close") {}
}
Not an ideal condition but if you to add more buttons for some reason then wrap them inside a Group and alert will add ScrollView by default to make all button available to your app.

.alert("This is an alert", isPresented: $showAlert) {
    Group {
        Button("OK") {}
        Button("Not OK") {}
        Button("Hmm OK") {}
        Button("Well OOOK") {}
        Button("But wait") {}
        Button("Can I say something?") {}
        Button("Why close") {}
        Button("Only if you want to close") {}
        Button("Think again") {}
        Button("OK close") {}
    }
    Group {
        Button("OK") {}
        Button("Not OK") {}
        Button("Hmm OK") {}
        Button("Well OOOK") {}
        Button("But wait") {}
        Button("Can I say something?") {}
        Button("Why close") {}
        Button("Only if you want to close") {}
        Button("Think again") {}
        Button("OK close") {}
    }
}
We will return to the most common use case by having just two buttons for our alert.

.alert("This is an alert", isPresented: $showAlert) {
    Button("OK") {}
    Button("Cancel") {}
}
Since Button view takes role parameter, we will make use of that while creating buttons for our alert. We will make cancel button’s role as .cancel.

.alert("This is an alert", isPresented: $showAlert) {
    Button("OK") {}
    Button("Cancel", role: .cancel) {}
}
Adding role to button brings out an interesting aspect of alert modifier. If have all kind of button roles but none is marked as cancel, framework adds one and provides it by default.

We will change our cancel button title and role.

.alert("This is an alert", isPresented: $showAlert) {
    Button("OK") {}
    Button("Hmm OK", role: .destructive) {}
}
Notice that system has added a cancel button. If we replace “Hmm OK” button to cancel from destructive role, the default button will do away.

If we want to add message to the alert, we can do that with another overload of alert modifier which takes message as parameter.

.alert("This is an alert", isPresented: $showAlert) {
    Button("OK") {}
    Button("Hmm OK", role: .cancel) {}
} message: {
    Text("Message: learn iOS with DevTechie")
}
Note: formatting modifiers don’t work with message parameter. Following will not work.
message: {
    Text("Message: learn iOS with DevTechie")
        .font(.largeTitle)
}
Note: alert with two buttons and if one of the button has cancel role, then the button with cancel will go to the leading side. It can be better understood with an example:
.alert("This is an alert", isPresented: $showAlert) {
    Button("Button 1") {}
    Button("Button 2", role: .cancel) {}
}
We can pass custom data to the alert modifier as well. We do this by using presenting parameter. We will update our example to pass details string to be used by alert’s body and message parameter.

struct DevTechieAlertsExample: View {
    @State private var showAlert = false
    @State private var details = "Visit DevTechie.com"
    
    var body: some View {
        NavigationView {
            VStack {
                Text("Learn iOS with DevTechie")
                    .font(.largeTitle)
                    .foregroundColor(.white)
                    .padding()
                    .background(.orange, in: RoundedRectangle(cornerRadius: 20))
                Button {
                    showAlert.toggle()
                } label: {
                    Text("Show alert")
                }
                .alert("This is an alert", isPresented: $showAlert, presenting: details) { someDetails in
                    Button(someDetails) {}
                    Button("Cancel", role: .cancel) {}
                } message: { someDetails in
                    Text("Message: \(someDetails)")
                }
                
            }
        }
    }
}
Examples we have seen uses button to toggle the State parameter but alert can be launched by any view as long as the State parameter attached to isPresenting changes its state.



With that we have reached the end of this article. Thank you once again for reading. Don’t forget to follow 😍. Also subscribe our newsletter at https://www.devtechie.com