En el vasto universo de la programación Swift, la navegación y la accesibilidad a las acciones principales son la columna vertebral de una buena experiencia de usuario. Si vienes del mundo de UIKit, recordarás las complejidades de gestionar UINavigationBar y UIToolbar por separado. Sin embargo, para un iOS developer moderno que utiliza Xcode y SwiftUI, Apple ha unificado estos conceptos en una herramienta poderosa y polimórfica: la Toolbar.
En este tutorial exhaustivo, desglosaremos qué es exactamente una toolbar en el paradigma declarativo, cómo añadir toolbar en SwiftUI de manera eficiente y cómo adaptar tu código para que funcione mágicamente en iOS, macOS y watchOS. Prepárate para elevar el nivel de tus aplicaciones.
¿Qué es realmente una Toolbar en SwiftUI?
A diferencia de UIKit, donde una barra de herramientas era un objeto visual específico anclado en la parte inferior o superior, en SwiftUI una Toolbar es una descripción semántica de acciones. No le dices al sistema “dibuja un botón en el píxel (x, y)”; le dices “necesito una acción de confirmación en esta vista”.
El sistema, dependiendo de la plataforma (iOS, iPadOS, macOS, watchOS), decide dónde colocar ese botón. Esto es fundamental para la filosofía de “escribe una vez, ejecuta en cualquier lugar” de la programación swift.
- En iOS: Puede aparecer en la barra de navegación superior o en una barra inferior.
- En macOS: Se integra en la barra de título de la ventana o en la Touch Bar.
- En watchOS: Se adapta a las esquinas superiores o menús contextuales.
Tu Primera Toolbar: Implementación Básica
Para empezar a añadir toolbar en SwiftUI, necesitamos un contexto de navegación. Desde iOS 16, el estándar es usar NavigationStack. El modificador clave es .toolbar().
Veamos un ejemplo sencillo donde añadimos un botón de “Guardar” a nuestra pantalla.
import SwiftUI
struct BasicToolbarView: View {
var body: some View {
NavigationStack {
VStack {
Image(systemName: "globe")
.imageScale(.large)
.foregroundColor(.accentColor)
Text("Hola, iOS Developer")
}
.navigationTitle("Inicio")
.toolbar {
Button("Guardar") {
print("Documento guardado")
}
}
}
}
}
Por defecto, si no especificamos nada más, SwiftUI colocará este botón en la posición “automática”, que en un iPhone suele ser la esquina superior derecha de la barra de navegación (el área “Trailing”).
Controlando la Posición: ToolbarItem y ToolbarItemGroup
Un buen iOS developer necesita precisión. Para controlar dónde aparecen los elementos, envolvemos nuestros botones dentro de un ToolbarItem o un ToolbarItemGroup. Esto nos permite acceder al parámetro placement.
Posicionamiento en iOS (Top Bar vs Bottom Bar)
En el diseño de interfaces móviles, a veces necesitamos acciones a la izquierda (cancelar), a la derecha (guardar) o en la parte inferior (filtros, compartir). Veamos cómo distribuir estos elementos en Xcode.
struct AdvancedToolbarView: View {
var body: some View {
NavigationStack {
Text("Editor de Contenido")
.navigationTitle("Editar")
.toolbar {
// Botón a la izquierda (Leading)
ToolbarItem(placement: .topBarLeading) {
Button("Cancelar") {
print("Cancelado")
}
}
// Botón a la derecha (Trailing)
ToolbarItem(placement: .topBarTrailing) {
Button(action: { print("Guardado") }) {
Label("Guardar", systemImage: "square.and.arrow.down")
}
}
// Barra inferior (Bottom Bar)
ToolbarItemGroup(placement: .bottomBar) {
Button(action: { print("Filtro") }) {
Image(systemName: "line.3.horizontal.decrease.circle")
}
Spacer() // Empuja los iconos a los extremos
Button(action: { print("Nuevo") }) {
Image(systemName: "square.and.pencil")
}
}
}
}
}
}
Observa cómo usamos .topBarLeading y .topBarTrailing. En versiones anteriores de SwiftUI se usaba .navigationBarLeading, pero Apple ha actualizado la nomenclatura para ser más inclusiva con otras plataformas.
La Magia Semántica: Principal, Confirmation y Cancellation
Aquí es donde la programación swift brilla. En lugar de pensar en “izquierda” o “derecha”, deberíamos pensar en “acción principal” o “cancelación”. Si usas ubicaciones semánticas, tu app se verá nativa en cualquier idioma (incluidos los que se leen de derecha a izquierda como el árabe) y en cualquier dispositivo.
.cancellationAction: El sistema lo coloca donde el usuario espera encontrar un botón de “Cancelar” (izquierda en iOS, pero puede variar)..confirmationAction: Para acciones afirmativas como “Hecho”, “Guardar” o “Enviar”. Se suele colocar a la derecha y en negrita..principal: Coloca el contenido en el centro de la barra de navegación. Ideal para logotipos o selectores de segmento.
struct SemanticToolbarView: View {
@State private var text = ""
var body: some View {
NavigationStack {
TextField("Escribe algo...", text: $text)
.padding()
.navigationTitle("Nota")
.navigationBarTitleDisplayMode(.inline)
.toolbar {
// Colocación semántica: Confirmación
ToolbarItem(placement: .confirmationAction) {
Button("Hecho") {
// Lógica de guardado
}
}
// Colocación semántica: Cancelación
ToolbarItem(placement: .cancellationAction) {
Button("Cerrar") {
// Lógica de cierre
}
}
// Colocación Principal (Centro)
ToolbarItem(placement: .principal) {
VStack {
Text("Detalles").font(.headline)
Text("Editando ahora").font(.caption2).foregroundStyle(.secondary)
}
}
}
}
}
}
Al usar .principal, puedes reemplazar el título estándar de texto por cualquier vista compleja, como un icono de marca o un subtítulo dinámico, algo muy demandado por cualquier cliente a un ios developer.
Toolbar en el Teclado (Keyboard Toolbar)
Una de las características más solicitadas en el desarrollo de formularios es la capacidad de añadir botones sobre el teclado (como “Siguiente” o “Listo”). En UIKit requeríamos un inputAccessoryView. Al añadir toolbar en SwiftUI, esto es increíblemente sencillo usando .keyboard.
struct KeyboardToolbarView: View {
@State private var name: String = ""
@FocusState private var isInputActive: Bool
var body: some View {
NavigationStack {
Form {
TextField("Tu nombre", text: $name)
.focused($isInputActive)
}
.toolbar {
ToolbarItemGroup(placement: .keyboard) {
Spacer() // Empuja el botón a la derecha
Button("Listo") {
isInputActive = false // Cierra el teclado
}
.bold()
}
}
}
}
}
Este código crea automáticamente una barra sobre el teclado virtual de iOS con un botón “Listo” alineado a la derecha. El Spacer() es crucial para que el botón no aparezca a la izquierda.
Adaptación Multiplataforma: macOS y watchOS
El poder de SwiftUI reside en su capacidad de adaptación. El mismo código que acabamos de escribir se comporta de manera diferente (y correcta) en otras plataformas.
macOS
En macOS, los elementos definidos con .primaryAction o .automatic a menudo se mueven fuera del área de contenido y se colocan en la parte superior de la ventana, al lado del título. Los elementos en .bottomBar no existen como tal en las ventanas estándar de Mac, por lo que SwiftUI intenta adaptarlos o deberás usar compilación condicional (#if os(macOS)) para cambiar el diseño.
watchOS
En el Apple Watch, el espacio es premium. La toolbar suele colocar el botón principal (.primaryAction) debajo de la barra de navegación o flotando en la parte superior izquierda. Si usas NavigationStack, el botón suele aparecer en la esquina superior opuesta al reloj.
#if os(watchOS)
// Código específico para ajustar la toolbar en el reloj si es necesario
#endif
Estado y Visibilidad de la Toolbar
Como ios developer, a menudo necesitarás ocultar o mostrar la toolbar dinámicamente. SwiftUI ofrece modificadores para esto.
.toolbarBackground(.visible, for: .navigationBar) // Fuerza la visibilidad del fondo
.toolbarBackground(Color.blue, for: .navigationBar) // Cambia el color
.toolbarColorScheme(.dark, for: .navigationBar) // Fuerza texto blanco
También es común deshabilitar botones de la toolbar basándose en la validación de un formulario. Simplemente usa el modificador estándar .disabled() en el botón dentro de la toolbar.
ToolbarItem(placement: .confirmationAction) {
Button("Enviar") {
submitData()
}
.disabled(text.isEmpty) // Se deshabilita si no hay texto
}
Novedad en iOS 16: ToolbarTitleMenu
Una característica muy moderna que vemos en aplicaciones como “Archivos” o “Notas” de Apple es un menú desplegable al tocar el título de la navegación. Esto se logra con .toolbarTitleMenu.
.navigationTitle("Documento")
.toolbarTitleMenu {
Button("Renombrar") { ... }
Button("Exportar") { ... }
Button(role: .destructive, action: { ... }) {
Label("Eliminar", systemImage: "trash")
}
}
Esto añade automáticamente una pequeña flecha junto al título y despliega un menú nativo, elevando la calidad percibida de tu aplicación.
Mejores Prácticas para el Desarrollo Profesional
Para cerrar este tutorial, aquí tienes una lista de consejos para aplicar en Xcode y mejorar tu flujo de trabajo en programación swift:
- Usa Label en lugar de Text: Dentro de una toolbar,
Label("Guardar", systemImage: "disk")es superior. En iOS mostrará el icono, pero en contextos de accesibilidad (VoiceOver) leerá el texto. En macOS, puede mostrar ambos dependiendo de la configuración del usuario. - No abuses del Bottom Bar: En iPhones modernos sin botón de inicio, la barra inferior compite con la barra de gestos del sistema. Úsala con moderación.
- Prueba la Rotación: Lo que se ve bien en vertical puede saturar la barra en horizontal. SwiftUI suele manejar esto colapsando items, pero siempre verifícalo.
- Semántica sobre Posición: Siempre que puedas, usa
.confirmationActionen lugar de.topBarTrailing. Esto garantiza la consistencia del sistema en futuras actualizaciones de iOS.
Conclusión
Aprender a añadir toolbar en SwiftUI es un paso fundamental para cualquier iOS developer. Hemos pasado de colocar botones manualmente a declarar intenciones semánticas que el sistema operativo interpreta de manera inteligente.
La próxima vez que abras Xcode para iniciar un proyecto, recuerda que la toolbar no es solo un adorno, es el centro de control de tu interfaz. Utiliza ToolbarItem, aprovecha el teclado con .keyboard y no olvides experimentar con las novedades como toolbarTitleMenu.
Si tienes cualquier duda sobre este artículo, contacta conmigo y estaré encantado de ayudarte 😊. Puedes contactar conmigo en mi perfil de X o en mi perfil de Instagram










