wandres.dev
SWIFTUI ESENCIAL · vistas y estado

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.

⏱ 17 min

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.

🎯 Al terminar esta lección sabrás
  • Mostrar datos con List y ForEach.
  • Por qué las listas necesitan Identifiable.
  • Navegar entre pantallas con NavigationStack.
  • Recoger datos con Form y 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)
}
ℹ️
Por qué Identifiable

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)
        }
    }
}

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.

💡
NavigationStack, no NavigationView

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()
                }
        }
    }
}
Ya sabes construir una app entera

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.

⚔️ Una mini-app de tareas
  1. Crea un modelo Tarea: Identifiable y un array de ejemplo.
  2. Muéstralo en una List con filas de HStack (icono + título).
  3. Envuélvelo en NavigationStack con navigationTitle y NavigationLink a una vista de detalle.
  4. Crea un Form para una tarea nueva con TextField, Toggle y Stepper.
  5. Presenta ese formulario con un botón en la .toolbar y .sheet.