Listas, navegación y formularios
Muestra colecciones con List y ForEach, navega entre pantallas con NavigationStack, y recoge datos con Form. Las tres piezas de casi cualquier app.
La mayoría de las apps son, en esencia, listas de cosas por las que navegas: correos, tareas, productos. SwiftUI hace esto sencillo y elegante con List, ForEach y NavigationStack. Con esta lección ya podrás construir apps de verdad.
- Mostrar datos con
ListyForEach. - Por qué las listas necesitan
Identifiable. - Navegar entre pantallas con
NavigationStack. - Recoger datos con
Formy presentar con.sheet.
List y ForEach
List crea una lista desplazable nativa. Con datos estáticos:
List {
Text("Manzana")
Text("Pera")
Text("Uva")
}
Para datos dinámicos, ForEach recorre una colección. Y aquí aparece Identifiable: cada fila necesita una identidad estable para que SwiftUI sepa cuál es cuál:
struct Tarea: Identifiable {
let id = UUID()
let titulo: String
}
let tareas = [Tarea(titulo: "Estudiar"), Tarea(titulo: "Entrenar")]
List(tareas) { tarea in
Text(tarea.titulo)
}
Cuando la lista cambia (añades, borras, reordenas), SwiftUI usa el id para animar exactamente la fila correcta en lugar de redibujar todo. Por eso tus modelos de datos casi siempre conforman a Identifiable — justo lo que viste en el Nivel 1. Un id = UUID() basta para empezar.
Filas con contenido rico
Cada fila puede ser cualquier vista. Combina lo aprendido:
List(tareas) { tarea in
HStack {
Image(systemName: "circle")
VStack(alignment: .leading) {
Text(tarea.titulo).font(.headline)
Text("Pendiente").font(.caption).foregroundStyle(.secondary)
}
}
}
Navegación con NavigationStack
Para moverte entre pantallas, envuelve tu contenido en un NavigationStack y usa NavigationLink:
NavigationStack {
List(tareas) { tarea in
NavigationLink(tarea.titulo) {
DetalleTarea(tarea: tarea) // pantalla destino
}
}
.navigationTitle("Tareas")
}
Al tocar una fila, SwiftUI apila la pantalla de detalle y añade el botón “atrás” automáticamente. navigationTitle pone el título de la barra.
Si ves tutoriales antiguos con NavigationView, están desactualizados: NavigationStack (iOS 16+) es el moderno, con mejor control del historial de navegación mediante rutas. Usa siempre NavigationStack.
Form: recoger datos
Form agrupa controles de entrada con el estilo nativo de Ajustes de iOS:
struct NuevaTarea: View {
@State private var titulo = ""
@State private var prioridad = 1
@State private var urgente = false
var body: some View {
Form {
Section("Detalles") {
TextField("Título", text: $titulo)
Stepper("Prioridad: \(prioridad)", value: $prioridad, in: 1...5)
Toggle("Urgente", isOn: $urgente)
}
}
}
}
Cada control usa un $binding (Nivel 2.4) para conectarse al @State.
Presentar una hoja (.sheet)
Para mostrar una pantalla modal (crear algo, ver detalle) desde abajo:
struct Lista: View {
@State private var mostrandoNueva = false
var body: some View {
NavigationStack {
List { /* … */ }
.toolbar {
Button("Añadir", systemImage: "plus") {
mostrandoNueva = true
}
}
.sheet(isPresented: $mostrandoNueva) {
NuevaTarea()
}
}
}
}
Detente a ver lo que tienes: una lista de datos (List + ForEach + Identifiable), navegación a detalle (NavigationStack + NavigationLink), un formulario para crear (Form), y una hoja modal para presentarlo (.sheet + @State). Eso es la estructura de la mayoría de las apps de la App Store. Lo que falta —guardar los datos y traerlos de una API— son los Niveles 4 y 5. Pero la interfaz de una app real ya está a tu alcance.
- Crea un modelo
Tarea: Identifiabley un array de ejemplo. - Muéstralo en una
Listcon filas deHStack(icono + título). - Envuélvelo en
NavigationStackconnavigationTitleyNavigationLinka una vista de detalle. - Crea un
Formpara una tarea nueva conTextField,ToggleyStepper. - Presenta ese formulario con un botón en la
.toolbary.sheet.