SwiftUI in Action: A Deep Dive into Action Sheets and Confirmation Dialog

Action sheets in SwiftUI provide a way to present a selection of options or actions to the user in a visually appealing and interactive manner. They are particularly useful when you want to offer choices or gather input in response to a specific user action. With SwiftUI’s confirmationDialog() modifier in iOS 15 and later, creating action sheets is straightforward, allowing you to provide a title, control their visibility using a binding, and define the available options as buttons. For iOS 14 and earlier, the actionSheet() modifier offers similar functionality.

I am going to use a Shopping app as an example that I started developing for other tutorials about SwiftUI presentations like sheets and popovers.

Download the project files here: https://github.com/gahntpo/Sho…

In the following, I am going to show an action sheet when the user taps on the toolbar person button.

swiftui example for an action sheet and confirmation dialog

Understanding SwiftUI Action Sheets

An Action Sheet in SwiftUI is a specific kind of alert that presents a set of options to the user. It’s generally used when you want to offer multiple choices that dictate the app’s next action. In SwiftUI, you can present an Action Sheet by attaching the .actionSheet(isPresented:content:) modifier to a view. The isPresented parameter is a binding to a Boolean that determines whether the sheet is shown. The content parameter is a closure returning the Action Sheet to display.

For the above example, I am creating a separate view `UserProfileButtonView` that I add to the toolbar:

struct ContentView: View {
    @StateObject var fetcher = AutomaticProductFetcher()

    var body: some View {
        NavigationStack {
            ProductListView(products: fetcher.products,
                            state: fetcher.state)
            .toolbar {
                ToolbarItemGroup(placement: .navigation) {
                  UserProfileButtonView()
                }

                ToolbarItem {
                    Button {
                        showCategorySelector.toggle()
                    } label: {
                        Label("Choose Category", systemImage: "line.3.horizontal.decrease.circle")
                    }
                }
            }
            .navigationDestination(for: Product.self, destination: { product in
                ProductDetailView(product: product)
            })
        }
        .sheet(isPresented: $showCategorySelector) {
             ...
        }
    }
}

For the `UserProfileButtonView`, I am adding a button which toggles the `showActionSheet` state property. This state is used to show/ hide the action sheet. You have to define an ActionSheet which defines what is displayed inside the action sheet.

struct UserProfileButtonView: View {
    @State private var showActionSheet = false

    var body: some View {
        Button {
            showActionSheet.toggle()
        } label: {
            Image(systemName: "person.fill")
        }
        .actionSheet(isPresented: $showActionSheet) {
            userSheet()
        }
    }

    func userSheet() -> ActionSheet {

        let picturButton = ActionSheet.Button.default(Text("Change Profile Picture")) {  }
        let profileButton = ActionSheet.Button.default(Text("Edit Profile Information")) {  }
        let logOutButton = ActionSheet.Button.destructive(Text("Log Out")) {  }
        let cancelButton = ActionSheet.Button.cancel(Text("Cancel")) {  }

        let buttons: [ActionSheet.Button] = [picturButton, profileButton, logOutButton, cancelButton]

        return ActionSheet(title: Text("Change Your Profile"),
                           message: Text(""),
                           buttons: buttons)
    }
}

In this example I am showing 4 buttons:

  • `Change Profile`, and `Edit Profile Information` are of type default and use the apps accent color.
  • The `Log Out` button is a destructive actionsheet button and has a red foreground color.
  • The `Cancel` button is a cancel actionsheet button and displayed at the very bottom of the action list.

How to dismiss an action sheet?

In order to dismiss an action sheet, you can either tap on the area outside the action sheet or on one of the button options. You don’t have to call dismiss() inside the buttons, this is automatically done for you.

Free SwiftUI Layout Book

Get Hands-on with SwiftUI Layout.

Master SwiftUI layouts with real-world examples and step-by-step guide. Building Complex and Responsive Interfaces.

SwiftUI ConfirmationDialog for iOS 15 and macOS 13

ActionSheet was soft deprecated with the introduction iOS 15 and macOS 12. You can still use it, but I am going to show you the newer and easier-to-use alternative which is confirmationDialog.

struct UserProfileButtonView: View {

    @State private var showDialog = false

    var body: some View {
        Button {
            showDialog.toggle()
        } label: {
            Image(systemName: "person.fill")
        }
        .confirmationDialog("Change Your Profile",
                            isPresented: $showDialog) {
            Button("Change Profile Picture") { }
            Button("Edit Profile Information") { }

            Button("Log Out", role: .destructive) { }
            Button("Cancel", role: .cancel) { }
        }

    }
}

You can simply work with SwiftUI buttons, instead of the special type `ActionSheet.Button`. I used different button roles to achieve the same foreground color styling. You can learn more about button styling in this post SwiftUI Button Stylings.

Customizing the Appearance of Confirmation Dialog in SwiftUI

You can further change the appearance of the confirmation dialog. For example, you can add a message text that is shown below the title. Additionally, you can now use the titleVisibility parameter to hide the title.

import SwiftUI

struct ConfirmationDialogExampleView: View {
    @State var show = false

    var body: some View {
        Button("Open Confirmation Dialog") {
            show = true
        }
        .confirmationDialog(String("Are you sure?"),
                            isPresented: $show,
                            titleVisibility: .hidden) {
            Button("Yes") { }
            Button("No", role: .cancel) { }

        } message: {
            Text("This action cannot be undone. Would you like to proceed?")
        }
    }
}
swiftui confirmation dialog

Conclusion

That’s it! You’ve now taken a comprehensive tour through SwiftUI Action Sheets and Confirmation Dialogs, their structure, and their use in your applications. Remember, these elements are vital tools to create an interactive, user-friendly interface. With just a few lines of code, you can greatly enhance your app’s user experience. So don’t hesitate to dive in, experiment, and see how these features can bring your apps to life. Keep exploring, keep learning, and most importantly, keep coding!

Further Reading:

Leave a Comment

Subscribe to My Newsletter

Want the latest iOS development trends and insights delivered to your inbox? Subscribe to our newsletter now!

Newsletter Form

New Course Announcement!!!

50% OFF Launch Sale

MacOS Development with SwiftUI