Table of Contents
SwiftUI, el marco declarativo de Apple para construir interfaces de usuario en todas las plataformas de Apple, proporciona una forma potente pero sencilla de crear interfaces de varias pestañas. La navegación pulsada es uno de los patrones más comunes en aplicaciones móviles y de escritorio, permitiendo a los usuarios cambiar rápidamente entre secciones distintas sin perder contexto. Ya sea que usted está construyendo una aplicación de noticias de alta calidad, un panel de productividad, o un panel de navegación [LT][
Este artículo recorre todo lo que necesitas saber sobre diseñar interfaces multitab con SwiftUI. Empezando con los conceptos básicos de TabView, exploraremos la personalización, la gestión estatal, los patrones avanzados, la accesibilidad, el rendimiento y los ejemplos del mundo real. Al final, estarás equipado para crear aplicaciones de tabulados de producción que deleiten a los usuarios.
Comprender el componente TabView
En el corazón de la navegación de pestañas en SwiftUI se encuentra TabView]. Es una vista de contenedor que presenta un conjunto de vistas infantiles, cada una asociada con un elemento de pestaña. Cuando el usuario toca una pestaña, se muestra la vista correspondiente, y la barra de pestañas muestra el estado activo con un punto culminante.
Disposición y comportamiento
Por defecto, TabView] hace una barra de pestañas en la parte inferior de la pantalla en iOS y en la parte superior en macOS. iPadOS se adapta a la orientación del dispositivo, y watchOS utiliza un estilo segmentado. No necesita gestionar la distribución de la barra de pestañas en sí; SwiftUI maneja la posición, el tamaño y la animación de la selección de la pestaña.
Artículos de pestaña con Símbolos de SF
Apple recomienda utilizar símbolos SF para los iconos de pestañas porque se escalan perfectamente a través de dispositivos y configuraciones de accesibilidad. El modificador acepta un constructor de vistas donde normalmente se coloca un con un nombre de símbolo SF y una etiqueta .
TabView {
ContentView()
.tabItem {
Label("Home", systemImage: "house.fill")
}
}
La vista Label combina automáticamente un icono y un título, garantizando una alineación adecuada y etiquetas de accesibilidad. Siempre puedes volver a separar y vistas para más control.
Construcción de una interfaz de tab múltiple básica
Crear una aplicación simple tabbed requiere sólo unas pocas líneas de código. Construyamos un ejemplo mínimo con tres pestañas: Inicio, Búsqueda y Perfil.
Aplicación de la medida
- Crear una nueva vista SwiftUI (por ejemplo, ) y añadir un TabView como la raíz.
- Para cada pestaña, proporcione una vista infantil (como una o una vista personalizada).
- Adjunte el modificador ] con un símbolo SF adecuado y una cadena localizada.
Ejemplo de código
struct ContentView: View {
var body: some View {
TabView {
HomeView()
.tabItem {
Label("Home", systemImage: "house.fill")
}
SearchView()
.tabItem {
Label("Search", systemImage: "magnifyingglass")
}
ProfileView()
.tabItem {
Label("Profile", systemImage: "person.crop.circle")
}
}
}
}
struct HomeView: View {
var body: some View {
Text("Welcome Home")
}
}
struct SearchView: View {
var body: some View {
Text("Find what you need")
}
}
struct ProfileView: View {
var body: some View {
Text("Your profile")
}
}
Este código produce una barra de pestañas de trabajo con tres elementos. Cada pestaña muestra su contenido respectivo cuando se selecciona. SwiftUI administra automáticamente las animaciones activas de estado y transición.
Personalización de artículos de la pestaña
Mientras que el aspecto predeterminado es limpio, a menudo necesita adaptar la barra de pestañas para que coincida con la marca de su aplicación o proporcionar comentarios adicionales de usuario.
Añadiendo placas e indicadores
SwiftUI permite adjuntar una placa a cualquier elemento de pestaña usando el modificador en la vista del niño. Las insignias muestran un pequeño número o texto (como el recuento de notificaciones no leídos). Por ejemplo:
TabView {
InboxView()
.tabItem { Label("Inbox", systemImage: "tray.fill") }
.badge(5) // Shows a red badge with "5"
SettingsView()
.tabItem { Label("Settings", systemImage: "gearshape") }
}
Las placas se actualizan automáticamente cuando están sujetas a @State] o bien observadas. En iOS, la placa aparece como un círculo rojo con un número; en otras plataformas, puede ser diferente.
Cambio de la apariencia de la barra de pestañas (Colores de pintura y fondo)
Para cambiar el color de acento de la pestaña seleccionada, establece el modificador en el TabView] (deprendido en versiones iOS nuevas) o utilice el modificador en iOS 15+:
TabView {
// tabs...
}
.tint(.purple)
Para una personalización más avanzada, como un fondo o forma personalizado, puede utilizar a través de o construir una barra de pestañas completamente personalizada utilizando una pila horizontal de botones (ver la sección de barras de pestañas personalizadas más adelante). Sin embargo, aferrarse a la barra de pestañas del sistema cuando sea posible garantiza un comportamiento coherente con las expectativas de los usuarios y los gestos de nivel del sistema.
Gestión del Estado y la Selección
Controlar qué pestaña está activa es esencial para características como el enlace profundo, las preferencias de los usuarios, o restablecer la aplicación a la primera pestaña después de una determinada acción.
Uso de @State para la selección
Ajustar una variable @State] del mismo tipo que los valores de la etiqueta al parámetro TabView. Asignar cada niño ver un entero (o cualquier valor) utilizando el modificador .
struct ContentView: View {
@State private var selectedTab = 0
var body: some View {
TabView(selection: $selectedTab) {
HomeView()
.tabItem { Label("Home", systemImage: "house.fill") }
.tag(0)
SearchView()
.tabItem { Label("Search", systemImage: "magnifyingglass") }
.tag(1)
ProfileView()
.tabItem { Label("Profile", systemImage: "person.crop.circle") }
.tag(2)
}
}
}
Cuando cambia (por ejemplo, a través de un botón en la pantalla de inicio), la vista de la pestaña cambia automáticamente a la pestaña correspondiente. Este enfoque también le permite leer la pestaña actual en otro lugar de su aplicación.
Interruptor de pestañas programáticas
Puede cambiar las pestañas desde dentro de cualquier vista infantil pasando una unión a la variable de selección. Por ejemplo, un botón “Ir a Ajustes” en la pestaña de inicio:
struct HomeView: View {
@Binding var selectedTab: Int
var body: some View {
VStack {
Text("Home")
Button("Open Settings") {
selectedTab = 2
}
}
}
}
Integrar esto pasando el vínculo al crear la vista del niño dentro del TabView]. Esto le da control completo sobre la navegación sin romper el estado de la pestaña.
Selección de pestañas persistentes con UserDefaults
Para un toque fácil de usar, recuerde la última pestaña seleccionada después de que la aplicación se reinicia. Use para persistir automáticamente la selección a UserDefaults:
struct ContentView: View {
@AppStorage("selectedTab") private var selectedTab = 0
var body: some View {
TabView(selection: $selectedTab) {
// tabs...
}
}
}
La aplicación ahora lanzará en la pestaña que el usuario visitó por última vez.
Patrones de navegación avanzados
Las aplicaciones multitab a menudo necesitan integrarse con pilas de navegación, manejar URLs entrantes o compartir datos entre pestañas.
Combinando TabView con NavigationView
Cada pestaña puede contener su propio (o en SwiftUI antiguo). Esto permite perforar en puntos de vista detallados dentro de una pestaña mientras la barra de pestañas permanece visible.
struct HomeView: View {
var body: some View {
NavigationStack {
List(1..<20) { item in
NavigationLink("Item \(item)", value: item)
}
.navigationDestination(for: Int.self) { item in
DetailView(item: item)
}
.navigationTitle("Home")
}
}
}
Coloque el dentro de la vista infantil de la pestaña, no fuera de TabView, para mantener las pilas de navegación separadas por pestaña. Este es el patrón recomendado para aplicaciones como Mail o Settings.
Manejo de los vínculos profundos
Cuando su aplicación recibe un enlace universal o un esquema de URL personalizado, es posible que necesite cambiar a una pestaña específica y navegar opcionalmente a una sub-visión. Utilice el modificador en el TabView (o la vista de la raíz) y parse la URL para actualizar el estado de selección o activar navegación.
TabView(selection: $selectedTab)
.onOpenURL { url in
// e.g., myapp://tab/2
if let tabNumber = extractTab(from: url) {
selectedTab = tabNumber
}
}
Para escenarios más complejos, combine con un camino de unión.
Pasando datos entre pestañas
Debido a que cada pestaña tiene su propia jerarquía de visión, pasar datos entre ellos requiere una fuente de estado compartida.
- Objetos de medio ambiente: Inyectar a través en la raíz de TabView].
- EstadoObjeto con un gerente compartido: Crear una clase de un solotón o observable y pasarla.
- Usando la unión de selección: Para valores simples, el propio Estado de selección puede actuar como canal de comunicación (por ejemplo, "Cambié a la pestaña 2 porque los datos están listos".
Evite la sobrecomplicación; mantenga el flujo de datos unidireccional cuando sea posible.
Accesibilidad y experiencia de usuario
Una interfaz de pestaña accesible es crucial para llegar a la audiencia más amplia. SwiftUI proporciona soporte de accesibilidad incorporado, pero debe verificar y mejorarlo.
Soporte de VoiceOver
Los elementos de la pestaña obtienen automáticamente etiquetas de accesibilidad de los Label]] o texto que proporcionas. Prueba que cada pestaña transmite su propósito claramente. Para las barras de pestaña personalizadas, agregue y ] para imitar el comportamiento del sistema.
Navegación de teclado
En iPadOS con un teclado de hardware, los usuarios pueden navegar entre pestañas usando Command‐[number] o Option‐Tab. La aplicación de la pestaña personalizada también admite comandos de teclado mediante la adición de .
Adaptive Layouts
En iPhones en modo de paisaje, la barra de pestañas puede aparecer de forma diferente. iOS 15 y luego permite que la barra de pestañas se ajuste cuando el espacio es limitado. Puede ajustar el contenido de la pestaña con para proporcionar una mejor experiencia de lectura o interacción.
Bares de Tab personalizados con SwiftUI
A veces necesitas un diseño que se desvía de la barra de pestañas del sistema —por ejemplo, un botón flotante en el centro, una forma curvada o iconos animados. Mientras pierdes algunos comportamientos incorporados (como los inicios de área segura), SwiftUI hace barras de pestaña personalizadas directamente.
TabView replicante con formas personalizadas
Cree una vista personalizada usando un de botones sobrepuestos en la parte inferior. Utilice para seleccionar y cambiar el contenido con una propiedad computada o una declaración dentro de un ].
struct CustomTabView: View {
@State private var selection = 0
var body: some View {
VStack(spacing: 0) {
// Content area
Group {
if selection == 0 {
HomeView()
} else if selection == 1 {
SearchView()
} else {
ProfileView()
}
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
// Custom tab bar
HStack {
TabBarButton(icon: "house.fill", label: "Home", isSelected: selection == 0)
.onTapGesture { selection = 0 }
Spacer()
TabBarButton(icon: "magnifyingglass", label: "Search", isSelected: selection == 1)
.onTapGesture { selection = 1 }
Spacer()
TabBarButton(icon: "person.fill", label: "Profile", isSelected: selection == 2)
.onTapGesture { selection = 2 }
}
.padding(.horizontal)
.padding(.top, 8)
.background(Color(uiColor: .systemBackground)
.shadow(radius: 2))
}
.ignoresSafeArea(.keyboard) // Prevent tab bar from moving with keyboard
}
}
Animando las transiciones de tab
Agregue transiciones suaves al cambiar las pestañas envolviendo el contenido en un bloque . Por ejemplo, agregue una transición de diapositivas o opacidad. También puede animar el icono en sí mismo utilizando en iOS 17+ (como el botazo o el pulso).
Optimización del rendimiento
Las aplicaciones multitab pueden sufrir de la memoria bloat si cargas todas las pestañas con entusiasmo. La pantalla TabView] es perezosa por defecto: sólo crea y hace la vista para la pestaña seleccionada. Sin embargo, si utilizas vistas inteligentes, puedes todavía querer optimizar.
Lazy Cargando Tab Contenido
Use o en las pestañas para aplazar la creación de la vista hasta el desplazamiento. Evite usar computaciones complejas en el inicializador de las vistas de los niños de la pestaña; en lugar, confíe en para iniciar la carga de datos.
Evitar los Líderes de memoria
Debido a que las pestañas suelen tener referencias a instancias, asegúrese de que no está creando ciclos de referencia fuertes innecesarios. Use para objetos de propiedad y para los compartidos. Si una pestaña nunca se muestra, su vista puede todavía ser sostenida en la memoria — use (un envoltorio personalizado) para aplazar la inicialización hasta que se seleccione la pestaña.
Probando su interfaz taquigráfica
Las pruebas automatizadas ayudan a asegurar que la navegación de la pestaña funciona correctamente en los estados del dispositivo.
Pruebas de unidad para selección de pestañas
Debido a que su vista de pestaña es impulsada por una variable , puede probar la lógica que cambia . Por ejemplo, validar que un enlace profundo se analiza correctamente y asigna el índice de pestañas.
func testTabSelectionViaDeepLink() {
let url = URL(string: "myapp://tab/2")!
let tabNumber = extractTab(from: url)
XCTAssertEqual(tabNumber, 2)
}
Pruebas de interfaz de usuario con XCTest
Utilice XCUITest para verificar que el uso de un elemento de pestaña muestra el contenido correcto. Acceso a los elementos de la pestaña por su etiqueta o identificador de accesibilidad.
func testTappingSearchTab() {
let app = XCUIApplication()
app.launch()
let searchTab = app.tabBars.buttons["Search"]
XCTAssertTrue(searchTab.exists)
searchTab.tap()
XCTAssertTrue(app.staticTexts["Find what you need"].exists)
}
Ejemplo del mundo real: un panel multi-tab
Traigamos todo junto con un ejemplo práctico: una aplicación de panel con tres pestañas — Resúmenes, Análisis y Ajustes.
Sinopsis
Muestra un resumen de las métricas clave (como usuarios activos diarios, ingresos) en un desplazamiento . Usos para permitir la perforación en informes detallados. La selección de pestañas se persiste con .
Analítica Tab
Contiene gráficos y gráficos construidos con gráficos Swift. Debido a que la renderización de gráficos puede ser pesada, marca la vista como y activa la carga de datos sólo cuando la pestaña aparezca.
Ajustes Tab
Muestra una lista de toggles, links y un botón de inicio de sesión. Esta pestaña puede necesitar acceso a un objeto de entorno que contenga la sesión del usuario. Pasando que a través de garantiza que todas las pestañas compartan los mismos datos.
Pitfalls y soluciones comunes
Incluso los desarrolladores experimentados de SwiftUI se encuentran en algunos problemas recurrentes con TabView.
Tab Bar Desapareciendo en el ataúd de navegación
Si empuja una vista sobre una pila de navegación dentro de una pestaña, la barra de pestañas puede desaparecer en el empuje. Solución: uso (iOS 16+) en lugar de – la barra de pestañas se mantiene visible. Alternativamente, ocultar manualmente la barra de pestañas utilizando el modificador .
Valores incorrectos de la etiqueta
Si no asignas a cada niño, la vista de la pestaña puede no honrar correctamente la selección. Siempre proporcionar una etiqueta distinta y factible para cada pestaña.
Tab View Resetting State
A veces, cuando se cambian las pestañas, el estado de la vista del niño se reasienta. Esto es por diseño – SwiftUI crea una nueva instancia de la vista del niño cada vez que necesita mostrarla. Para preservar los interruptores de pestañas del estado, levante el estado a una vista o uso de los padres a un nivel superior al TabView.
Conclusión
Diseñar una interfaz multitab con SwiftUI es tanto simple como profundamente personalizable. El componente TabView le da una base sólida, y con unas pocas líneas adicionales de código puede añadir insignias, administrar estado, integrar pilas de navegación e incluso construir barras de pestañas totalmente personalizadas. Siguiendo las mejores prácticas para la accesibilidad, el rendimiento y la prueba, crearás una plataforma de navegación pulida.
Continuar explorando inmersos en ]Documentación oficial de Apple ], aprendiendo sobre directrices de interfaz humana para barras de pestañas, y experimentando con Símbolos FSM] para dar a tus pestañas un aspecto pulido y consistente en el sistema.