TechnologiesSwiftUI

DismissSearchAction struct

iOSmacOStvOSwatchOSvisionOSiOS 15.0+✓ renders

An action that can end a search interaction.

How it works

DismissSearchAction is a callable structure that programmatically ends the current search interaction, clearing focus from the search field and dismissing any search-specific presentation that a searchable modifier installed. Reach for it when your own UI — a button, a row tap, a completed action — needs to take the user out of search mode rather than waiting for them to cancel manually. You never construct one yourself; SwiftUI vends a ready-made instance through the environment, and you invoke it like a function to trigger the dismissal.

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

    A DismissSearchAction is only meaningful inside a view that lives under a search context, so SwiftUI supplies it through the environment rather than an initializer. Declare a property with @Environment(\.dismissSearch) private var dismissSearch to bind the current action, as SearchResults does. The value is always present, but it only has an effect when the surrounding scope is actually searching.

  2. Invoke the action as a function with dismissSearch()

    DismissSearchAction conforms to the call-as-function pattern, meaning you trigger it by calling the bound value directly — dismissSearch() — with no arguments and no return value. Here it runs inside the Button("Done") action, so tapping Done resigns the search field's focus and collapses the search presentation in one call.

  3. Establish the search context that the action acts on

    The action has nothing to dismiss unless a search scope exists above it. The .searchable(text: $query, prompt: "Search fruits") modifier on SearchResults is what activates search and what dismissSearch() later tears down; the bound query state stays intact, since dismissing search ends the interaction without erasing the typed text.

  4. Place the consuming view inside the searchable hierarchy

    Because the environment value flows down the view tree, the view that calls the action must be a descendant of the view carrying .searchable. In the example SearchResults both declares .searchable and reads \.dismissSearch, so its Button is correctly positioned to dismiss the search it owns.

Try it — Add a print(query) line right before dismissSearch() in the Button("Done") action, type into the field, then tap Done to confirm the search dismisses while the entered text is preserved.

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.

DismissSearchAction.swift
struct DismissSearchActionDemo: View {
    @State private var query = ""

    var body: some View {
        NavigationStack {
            SearchResults()
                .searchable(text: $query, prompt: "Search fruits")
                .navigationTitle("Fruits")
        }
    }
}

struct SearchResults: View {
    @Environment(\.dismissSearch) private var dismissSearch

    var body: some View {
        List {
            Text("Apple")
            Text("Banana")
            Button("Done") {
                dismissSearch()
            }
        }
        .padding()
    }
}
Live preview
Search fruits 9:41 Fruits
Search fruits 9:41 Fruits
swift → lexer → parser → sema → uiir → canvas Open in Studio ↗
What's new in SwiftUI 27 →