New in SwiftUI 3: ConfirmationDialog in SwiftUI and iOS 15

DevTechie Inc
Apr 6, 2022
Introduced in iOS 15, confirmationDialog modifier gives a way to show actionSheet on iPhone and popover menu on iPad. confirmationDialog is supported across the Apple platform which used SwiftUI so it will work for iOS, iPadOS, macOS and watchOS. If we want to show actionSheet on iOS 14 or below, you must use actionSheet modifier(ActionSheet is not available for macOS).

Let’s take a simple example of confirmationDialog:

struct SimpleConfirmationDialogExample: View {
    
    @State private var showChoice = false
    @State private var selectedFruit = "None"
    
    var body: some View {
        VStack {
            Text(selectedFruit)
            
            Button("Show fruit choice") {
                showChoice = true
            }
            .confirmationDialog("Which fruit would you like to eat?", isPresented: $showChoice) {
                Button("Apple") {
                    selectedFruit = "Apple"
                }
                
                Button("Banana") {
                    selectedFruit = "Banana"
                }
            }
        }
    }
}
In this example, we are creating two state properties.

showChoice will help us control the visibility of confirmationDialog.

selectedFruit will store selected choice.

We will also have a button which will set showChoice to true in order for confirmationDialog to appear. Content parameter of confirmationDialog is a view builder returning the dialog’s actions.

Output:

Did you notice Cancel action button🤨? We never added that, the modifier adds it for convenience 👍.

You can use new role parameter with Button to hint the button type for user.

struct SimpleConfirmationDialogExample: View {
    
    @State private var showChoice = false
    @State private var selectedFruit = "None"
    
    var body: some View {
        VStack {
            Text(selectedFruit)
            
            Button("Show fruit choice") {
                showChoice = true
            }
            .confirmationDialog("Which fruit would you like to eat?", isPresented: $showChoice) {
                Button("Apple", role: .destructive) {
                    selectedFruit = "Apple"
                }
                
                Button("Banana", role: .destructive) {
                    selectedFruit = "Banana"
                }
            }
        }
    }
}
Output:

Not sure if you noticed or not but our label is missing 😅. In the following line we are setting label for confirmationDialog:

.confirmationDialog("Which fruit would you like to eat?", isPresented: $showChoice)
But we don’t see that but there is a way to show the label, by setting titleVisibility parameter for confimationDialog.

struct SimpleConfirmationDialogExample: View {
    
    @State private var showChoice = false
    @State private var selectedFruit = "None"
    
    var body: some View {
        VStack {
            Text(selectedFruit)
            
            Button("Show fruit choice") {
                showChoice = true
            }
            .confirmationDialog("Which fruit would you like to eat?", isPresented: $showChoice, titleVisibility: .visible) {
                Button("Apple", role: .destructive) {
                    selectedFruit = "Apple"
                }
                
                Button("Banana", role: .destructive) {
                    selectedFruit = "Banana"
                }
            }
        }
    }
}
output:

Note that setting titleVisibility is only a suggestion and system can choose to ignore depending upon the context and platform its being shown.

All actions dismiss the confirmation dialog after action finished running. Default button is only displayed if none of the action button have .cancel role so if you like to remove cancel button, simply change one of the button’s role to be .cancel

struct SimpleConfirmationDialogExample: View {
    
    @State private var showChoice = false
    @State private var selectedFruit = "None"
    
    var body: some View {
        VStack {
            Text(selectedFruit)
            
            Button("Show fruit choice") {
                showChoice = true
            }
            .confirmationDialog("Which fruit would you like to eat?", isPresented: $showChoice, titleVisibility: .visible) {
                Button("Apple", role: .destructive) {
                    selectedFruit = "Apple"
                }
                
                Button("Banana", role: .cancel) {
                    selectedFruit = "Banana"
                }
            }
            
        }
    }
}
Output:

This also mean that your cancel action becomes the default selection.

Actions can be built dynamically as well:

struct SimpleConfirmationDialogExample: View {
    
    @State private var showChoice = false
    @State private var selectedFruit = "None"
    
    private var options: [String] = ["Apple", "Orange", "Banana"]
    
    var body: some View {
        VStack {
            Text(selectedFruit)
            
            Button("Show fruit choice") {
                showChoice = true
            }
            .confirmationDialog("Which fruit would you like to eat?", isPresented: $showChoice, titleVisibility: .visible) {
                ForEach(options, id: \.self) { opt in
                    Button(opt) {
                        selectedFruit = opt
                    }
                }
            }
            
        }
    }
}
Same code works on iPad as well:

Notice that there is no cancel button on iPad, instead user can tap anywhere to cancel out from the menu option.

With that, we have reached the end of this article. Thank you once again for reading, if you liked it, don’t forget to subscribe our newsletter.