TechnologiesSwiftUI

DismissAction struct

iOSmacOStvOSwatchOSvisionOSiOS 15.0+✓ renders

An action that dismisses a presentation.

How it works

DismissAction is a callable value that closes the current presentation — a sheet, popover, cover, or pushed view — without requiring the view to hold a binding to whatever presented it. SwiftUI hands you one through the environment, so a presented view can ask to be dismissed on its own terms instead of coordinating with its presenter through shared state. Reach for it whenever a child view owns a Done or Cancel action and you want it decoupled from the boolean or navigation state that drives the presentation.

  1. Read the action from the environment with @Environment(\.dismiss)

    SwiftUI publishes the current dismiss action under the \.dismiss environment key, scoped to whatever presentation contains the view. You bind it into a stored property with the @Environment property wrapper, as in @Environment(\.dismiss) private var dismiss inside SheetContent. The view never sees, and never needs, the showingSheet binding that the parent used to present it.

  2. Call the value directly to dismiss

    DismissAction is a struct that conforms to the callable pattern, so you invoke it like a function with no arguments — dismiss(). That single call tells SwiftUI to dismiss the nearest active presentation, here closing the sheet from inside its own Button("Dismiss") action closure.

  3. Let the presentation context resolve what gets closed

    The same dismiss() call adapts to its surroundings: it closes a sheet, dismisses a popover or fullScreenCover, or pops a view from a NavigationStack, depending on how the view was shown. Because SheetContent was placed by .sheet(isPresented:), calling dismiss resolves to dismissing that sheet — no code in the child needs to know which presentation style was used.

  4. Keep presenter and content decoupled

    Since the action travels through the environment, the presenting view keeps ownership of its own state — @State private var showingSheet lives only in DismissActionDemo — while the presented SheetContent stays self-contained and reusable across different presentation sites. Dismissing flips the presenter's state back for you without the child touching it.

Try it — Replace the body of the Button("Dismiss") action closure with print("tapped") instead of dismiss(), and the sheet stays open on tap — confirming it is the dismiss() call, not the button itself, that closes the presentation.

Example & preview

Press Run live & edit to compile it in your browser — then edit the Swift on the left and the preview re-renders live.

DismissAction.swift
struct DismissActionDemo: View {
    @State private var showingSheet = true

    var body: some View {
        Text("Main screen")
            .padding()
            .sheet(isPresented: $showingSheet) {
                SheetContent()
            }
    }
}

struct SheetContent: View {
    @Environment(\.dismiss) private var dismiss

    var body: some View {
        VStack(spacing: 16) {
            Text("Sheet Presented")
                .font(.headline)
            Button("Dismiss") {
                dismiss()
            }
            .buttonStyle(.borderedProminent)
        }
        .padding()
    }
}
Live preview
Main screen
Main screen
swift → lexer → parser → sema → uiir → canvas Open in Studio ↗
What's new in SwiftUI 27 →