Un NavigationStack puede incluir una barra de búsqueda, para lo cual se debe aplicar el siguiente modificador:
-
searchable(text:tokens:suggestedTokens:placement:prompt:token:):textes el texto introducido por el usuario.tokenssigue el rastro de los tokens mostrados al usuario.suggestedTokenstiene una lista de los tokens para sugerir valores al usuario.placementes la ubicación de la barra (que puede serautomatic,navigationBarDrawer,navigationBarDrawer(displayMode:),sidebarytoolbar).promptes el placeholder.tokenson las vistas para mostrar los tokens.
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 de búsqueda queda en la parte inferior de la pantalla porque tiene SearchFieldPlacement en automatic, que en iOS, MacOS y iPadOS sería lo mismo que toolbar. Cuando la barra se vuelve el "first responder", queda encima del teclado cuando este se presenta.
Notar que para que funcionase el ejemplo anterior, filteredPeople se hizo una variable computada y no almacenada. De lo contrario, habría sido necesario usar una aproximación basada en onChange(of:initial:_:), teniendo en cuenta que se debe marcar initial=true para que se cargue la información en filteredPeople en el arranque.
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 = if searchText.isEmpty {
people
} else {
people.filter { $0.name.localizedStandardContains(searchText) }
}
}
}
Visibilidad de la barra de búsqueda
Cuando la barra de búsqueda usa la ubicación por defecto (i.e. automatic) o toolbar, siempre será visible. Si hacemos que aparezca en la barra de navegación con navigationBarDrawer, entonces la barra de búsqueda desaparecerá cuando desplacemos la lista hacia arriba, y volverá a aparecer cuando la desplacemos hacia abajo.
Para que la barra de búsqueda siempre sea visible en la barra de navegación, se puede usar navigationBarDrawer(displayMode:), pasando always como argumento.
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?")
}
}
}
Activando la barra de búsqueda de forma programática
Se puede fijar/quitar el foco sobre una barra de búsqueda de forma programática a través del modificador searchFocused(_:) usando un Binding de tipo Bool con el "property-wrapper" FocusState.
En el siguiente ejemplo, el botón "Buscar" del toolbar, pone isFocused en true, lo que enfoca la barra de búsqueda y muestra el teclado.
struct ContentView: View {
@State private var searchText: String = ""
// ⚠️ Notar el uso de @FocusState
@FocusState private var isFocused: Bool
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(content: {
ToolbarItem(placement: .topBarTrailing) {
Button("Buscar", systemImage: "magnifyingglass") {
// ⚠️ Aquí se cambia isFocused para centrar el foco
// en la barra de búsqueda
isFocused = true
}
}
})
.searchable(text: $searchText, placement: .navigationBarDrawer(displayMode: .automatic), prompt: "¿A quién busca?")
// ⚠️ por medio de searchFocused se puede cambiar el foco
.searchFocused($isFocused)
}
}
}





Top comments (0)