[SUI] Barra de búsqueda

Published: (February 2, 2026 at 05:02 PM EST)
3 min read
Source: Dev.to

Source: Dev.to

Barra de búsqueda en NavigationStack

Un NavigationStack puede incluir una barra de búsqueda mediante el modificador searchable.
Su firma es:

searchable(
    text: Binding,
    tokens: Binding? = nil,
    suggestedTokens: [Token]? = nil,
    placement: SearchFieldPlacement = .automatic,
    prompt: String? = nil,
    token: () -> TokenView? = { nil }
)
  • text: texto introducido por el usuario.
  • tokens: seguimiento de los tokens mostrados.
  • suggestedTokens: lista de tokens sugeridos.
  • placement: ubicación de la barra (automatic, navigationBarDrawer, sidebar, toolbar, etc.).
  • prompt: placeholder.
  • token: vista para mostrar los tokens.

Uso básico

struct Person: Identifiable {
    let id = UUID()
    let name: String
}

private let people: [Person] = [
    .init(name: "David Goyes"),
    .init(name: "Midoriya Izuku"),
    .init(name: "Tanjiro Kamado"),
    .init(name: "David Beckham"),
]

struct ContentView: View {
    @State private var searchText: String = ""

    private var filteredPeople: [Person] {
        if searchText.isEmpty {
            people
        } else {
            people.filter { $0.name.localizedStandardContains(searchText) }
        }
    }

    var body: some View {
        NavigationStack {
            List(filteredPeople) { person in
                Text(person.name)
            }
            .navigationTitle("Personas")
            .searchable(text: $searchText, prompt: "¿A quién busca?")
        }
    }
}

En iOS 26, por defecto la barra se coloca en la parte inferior (equivalente a toolbar). Cuando se vuelve el first responder, aparece encima del teclado.

Actualizando la lista con onChange

Si se prefiere almacenar el resultado filtrado, es necesario actualizarlo manualmente:

struct ContentView: View {
    @State private var searchText: String = ""
    @State private var filteredPeople: [Person] = []

    var body: some View {
        NavigationStack {
            List(filteredPeople) { person in
                Text(person.name)
            }
            .navigationTitle("Personas")
            .searchable(text: $searchText, prompt: "¿A quién busca?")
            .onChange(of: searchText, initial: true) {
                filterPeople()
            }
        }
    }

    private func filterPeople() {
        filteredPeople = searchText.isEmpty
            ? people
            : people.filter { $0.name.localizedStandardContains(searchText) }
    }
}

Ubicaciones de la barra de búsqueda

  • automatic / toolbar: siempre visible en la barra inferior.
  • navigationBarDrawer: desaparece al desplazar la lista hacia arriba y reaparece al desplazarse hacia abajo.

Para mantenerla siempre visible en la barra de navegación:

struct ContentView: View {
    @State private var searchText: String = ""

    private var filteredPeople: [Person] {
        if searchText.isEmpty {
            people
        } else {
            people.filter { $0.name.localizedStandardContains(searchText) }
        }
    }

    var body: some View {
        NavigationStack {
            List(filteredPeople) { person in
                Text(person.name)
            }
            .navigationTitle("Personas")
            .searchable(
                text: $searchText,
                placement: .navigationBarDrawer(displayMode: .always),
                prompt: "¿A quién busca?"
            )
        }
    }
}

Enfoque programático con searchFocused

Se puede controlar el foco de la barra mediante searchFocused(_:) y un @FocusState:

struct ContentView: View {
    @State private var searchText: String = ""
    @FocusState private var isFocused: Bool   // <-- foco de la barra

    private var filteredPeople: [Person] {
        if searchText.isEmpty {
            people
        } else {
            people.filter { $0.name.localizedStandardContains(searchText) }
        }
    }

    var body: some View {
        NavigationStack {
            List(filteredPeople) { person in
                Text(person.name)
            }
            .navigationTitle("Personas")
            .toolbar {
                ToolbarItem(placement: .topBarTrailing) {
                    Button("Buscar", systemImage: "magnifyingglass") {
                        isFocused = true               // enfoca la barra
                    }
                }
            }
            .searchable(
                text: $searchText,
                placement: .navigationBarDrawer(displayMode: .automatic),
                prompt: "¿A quién busca?"
            )
            .searchFocused($isFocused)               // controla el foco
        }
    }
}

El botón “Buscar” del toolbar establece isFocused en true, lo que muestra el teclado y coloca el cursor en la barra de búsqueda.

Back to Blog

Related posts

Read more »

[SUI] LabeledContent

LabeledContenthttps://developer.apple.com/documentation/swiftui/labeledcontent es un contenedor que adjunta una etiqueta a un control. Uso básico swift struct C...

[SUI] Formularios (Form)

Form Form es un contenedor para agrupar controles, principalmente usados para la configuración de alguna funcionalidad. Presenta los controles en un List con e...