Skip to content

Confirmation Dialogs (SwiftUI)

A SwiftUI guide for coding agents. Also covers confirmationdialog modifier, action sheet replacement, destructive action confirm, are you sure dialog ios, delete confirmation prompt.

The confirmationDialog view modifier (SwiftUI Release 3, iOS 15+) presents a system dialog before a dangerous action, such as deleting data. It adapts by size class: an action sheet in compact widths and a popover in regular widths.

Presenting the Dialog

The modifier takes a title (a Text or LocalizedStringKey), a boolean binding that controls presentation, and a ViewBuilder of text-only buttons for the actions.

struct ContentView: View {
  @StateObject var viewModel = ViewModel()
  @State private var confirmationShown = false

  var body: some View {
    List {
      ForEach(viewModel.messages, id: \.self) { message in
        Text(message)
          .swipeActions {
            Button(role: .destructive) {
              confirmationShown = true
            } label: {
              Image(systemName: "trash")
            }
          }
          .confirmationDialog("Are you sure?", isPresented: $confirmationShown) {
            Button("Yes") {
              withAnimation { viewModel.delete(message) }
            }
          }
      }
    }
  }
}

SwiftUI adds a cancel button for you, and it dismisses the dialog as soon as the user taps any action. You never reset the binding to false yourself.

Roles, Default Action, and Ordering

Provide a role: .cancel button only to replace the default cancel label. The system may reorder buttons by role and prominence; mark the default action with .keyboardShortcut(.defaultAction) to give it the higher prominence.

.confirmationDialog("Are you sure?", isPresented: $confirmationShown) {
  Button("Yes") {
    withAnimation { viewModel.delete(message) }
  }
  .keyboardShortcut(.defaultAction)

  Button("No", role: .cancel) {}
}

Title Visibility, Message, and Presented Data

titleVisibility takes automatic, visible, or hidden. A trailing message closure adds a line under the title. The presenting: parameter passes a value into both closures, so the dialog can name the item it is about to delete.

.confirmationDialog(
  "Are you sure?",
  isPresented: $confirmationShown,
  titleVisibility: .visible,
  presenting: message
) { message in
  Button("Yes, delete: \(message)") {
    withAnimation { viewModel.delete(message) }
  }
  .keyboardShortcut(.defaultAction)

  Button("No", role: .cancel) {}
} message: { message in
  Text(message)
}

Use this guidance in your coding agent

Install the Better Design MCP once. Your agent then loads this page with one call.

get-swiftui-guide({ topic: "swiftui-confirmation-dialogs" })
claude mcp add --scope user better-design --transport http https://better-design.com/api/mcp --header "Authorization: Bearer <YOUR_API_KEY>"
Browse related design systems