What You Will Build

A multi-step account deletion flow with a safety confirmation: the user taps "Delete My Account," a text field appears asking them to type DELETE, and only then can they confirm. After confirmation, a success state is shown. This pattern follows Apple's App Store guidelines for account deletion and is used in settings screens across apps that handle user accounts.

Why This Pattern Matters

Apple requires all apps with account creation to offer account deletion. But accidental deletion is catastrophic, so a confirmation step is essential. This tutorial shows a progressive disclosure pattern where each step requires explicit user action, combined with smooth transitions.

Key SwiftUI Concepts

  • Progressive disclosure with @State booleans controlling which UI elements appear.
  • .disabled() modifier to prevent the confirm button from working until the user types the exact confirmation text.
  • .transition() for smooth enter/exit animations on conditional views.

The Complete Deletion Flow

struct DeleteAccountDemo: View {
    @State private var showConfirmation = false
    @State private var confirmText = ""
    @State private var isDeleted = false

    var body: some View {
        VStack(spacing: 24) {
            if isDeleted {
                // Success state
                VStack(spacing: 16) {
                    Image(systemName: "checkmark.circle.fill")
                        .font(.system(size: 60))
                        .foregroundStyle(.green)
                    Text("Account Deleted")
                        .font(.title2.bold())
                    Button("Reset Demo") {
                        withAnimation {
                            isDeleted = false
                            showConfirmation = false
                            confirmText = ""
                        }
                    }
                    .buttonStyle(.bordered)
                }
                .transition(.scale.combined(with: .opacity))
            } else {
                Image(systemName: "person.crop.circle.badge.xmark")
                    .font(.system(size: 60))
                    .foregroundStyle(.red)

                Text("Delete Account")
                    .font(.title2.bold())

                Text("This action cannot be undone. All your data "
                   + "will be permanently removed.")
                    .font(.subheadline)
                    .foregroundStyle(.secondary)
                    .multilineTextAlignment(.center)
                    .padding(.horizontal)

                if showConfirmation {
                    VStack(spacing: 12) {
                        Text("Type DELETE to confirm")
                            .font(.caption)
                            .foregroundStyle(.secondary)

                        TextField("DELETE", text: $confirmText)
                            .textFieldStyle(.roundedBorder)
                            .autocorrectionDisabled()
                            .padding(.horizontal, 40)

                        Button("Confirm Deletion") {
                            withAnimation(.spring) {
                                isDeleted = true
                            }
                        }
                        .buttonStyle(.borderedProminent)
                        .tint(.red)
                        .disabled(confirmText != "DELETE")
                    }
                    .transition(.move(edge: .bottom)
                        .combined(with: .opacity))
                }

                if !showConfirmation {
                    Button("Delete My Account") {
                        withAnimation(.spring) {
                            showConfirmation = true
                        }
                    }
                    .foregroundStyle(.red)
                    .fontWeight(.semibold)
                }
            }
        }
        .padding()
        .animation(.spring, value: isDeleted)
    }
}

The Three States

  1. Initial: Warning icon, explanation text, and a red "Delete My Account" button.
  2. Confirmation: A text field requiring the user to type "DELETE" and a disabled confirm button that enables only when the text matches exactly.
  3. Success: A green checkmark with "Account Deleted" message and a reset button for the demo.

Tips and Pitfalls

  • .autocorrectionDisabled() prevents the system from autocorrecting "DELETE" to something else.
  • String comparison is case-sensitive: The user must type exactly "DELETE". For production, consider confirmText.uppercased() == "DELETE" to be more forgiving.
  • .spring animation on the confirm button appearance prevents jarring layout shifts.
  • In production: Make an API call in the confirm action and show a loading state before the success screen.

iOS Version: iOS 15+

Get New Tutorials by Email

No spam. Just clear, practical breakdowns you can apply right away.

Enjoy this tutorial?

Get new practical tech tutorials in your inbox.