← Back to archive

Development · SwiftUI

Offering choices with ActionSheet

Configure action buttons, manage presentation state, and compare ActionSheet with confirmationDialog.

Read the Korean original on Velog ↗English translation

Development archive cover

When a user needs to choose an action, a sheet of options can feel more appropriate than a central alert. The available API depends on the iOS versions the app supports.

ActionSheet for iOS 13 and 14

ActionSheet supports apps targeting iOS 13 and 14. It presents a set of choices, dismisses when an option is selected, and runs the associated action. For newer targets, use confirmationDialog.

struct ActionSheetStudy: View {
    
    @State var showActionSheet: Bool = false // State property
    
    var body: some View {
        Button("Click Here!") {
            showActionSheet.toggle() // Set showActionSheet to true
        }
        // ActionSheet view
        .actionSheet(isPresented: $showActionSheet) {
            ActionSheet(
                title: Text("Title"),
                message: Text("This is message."),
                buttons: [
                    .default(Text("Button 1")), // First button
                    .destructive(Text("Button 2")), // Second button
                    .cancel() // Cancel button
                ])
        }
    }
}

A default button performs an ordinary action. A cancel button dismisses without proceeding, while destructive marks an action such as deletion that deserves extra attention.

Customizing the options

Extract sheet construction into a function and use an enum to select the appropriate configuration.

struct ActionSheetStudy: View {
    
    @State var showActionSheet: Bool = false
    @State var actionSheetType: MyActionSheetType = .isOtherPost
    
    // Define the action sheet cases
    enum MyActionSheetType {
        case isMyPost
        case isOtherPost
    }
    
    var body: some View {
        VStack(spacing: 40) {
            Button("My Post") {
                actionSheetType = .isMyPost // MyPost case
                showActionSheet.toggle()
            }
            .actionSheet(isPresented: $showActionSheet, content: getActionSheet)
            Button("Other Post") {
                actionSheetType = .isOtherPost // OtherPost case
                showActionSheet.toggle()
            }
            .actionSheet(isPresented: $showActionSheet, content: getActionSheet)
        }
    }
    
    func getActionSheet() -> ActionSheet {
        
        let shareButton: ActionSheet.Button = .default(Text("Share"))
        let reportButton: ActionSheet.Button = .destructive(Text("Report"))
        let deleteButton: ActionSheet.Button = .destructive(Text("Delete"))
        
        // Build the sheet for the selected case
        switch actionSheetType {
        case .isMyPost:
            return ActionSheet(
                title: Text("My Post"),
                buttons: [
                    shareButton,
                    deleteButton,
                    .cancel()
                ])
        case .isOtherPost:
            return ActionSheet(
                title: Text("Other Post"),
                buttons: [
                    shareButton,
                    reportButton,
                    .cancel()
                ])
        }
    }
}

confirmationDialog for iOS 15 and later

confirmationDialog is the newer API for presenting these choices.

struct ActionSheetStudy: View {
    
    @State var showActionSheet: Bool = false // State property
    
    var body: some View {
        Button("Click Here!") {
            showActionSheet.toggle() // Set showActionSheet to true
        }
        // ActionSheet view
        .confirmationDialog("Title", isPresented: $showActionSheet, titleVisibility: .visible) {
            Button("Button 1") {} // First button
            Button("Button 2", role: .destructive) {} // Second button
            Button("Cancel", role: .cancel) {} // Cancel button
        } message: {
            Text("This is message.")
        }
    }
}
← Back to archive