Si eres un iOS Developer que trabaja en el ecosistema de Apple, sabes que el rendimiento y la experiencia de usuario son pilares fundamentales en cualquier aplicación. Desde la llegada de SwiftUI, la forma en que construimos interfaces ha cambiado drásticamente en comparación con UIKit. Sin embargo, con este nuevo paradigma surgen nuevas dudas arquitectónicas.
Uno de los debates más comunes y recurrentes al abrir Xcode es la elección del componente adecuado para mostrar colecciones de datos: List vs LazyVStack en SwiftUI.
A primera vista, ambos parecen resolver el mismo problema: renderizar iteraciones de datos en una columna vertical. Sin embargo, bajo el capó, sus comportamientos, su gestión de memoria y sus capacidades de diseño son radicalmente distintos. En este artículo, desgranaremos qué es cada uno, cuándo debes utilizarlos y cómo se comportan en diferentes plataformas como iOS, macOS y watchOS.
¿Qué es una List en SwiftUI?
La List es uno de los componentes más antiguos y robustos de SwiftUI. Si vienes del mundo de UIKit, puedes pensar en la List como el equivalente directo y modernizado de UITableView.
Una List está diseñada para mostrar filas de datos con un formato estandarizado por el sistema operativo. Está fuertemente ligada a las guías de diseño de Apple (Human Interface Guidelines), lo que significa que, por defecto, te proporcionará márgenes, separadores, fondos y comportamientos de scroll nativos sin que tengas que escribir código adicional.
Características Principales de la List
- Estilo Nativo Integrado: Las listas vienen con estilos predefinidos (
.listStyle()) comoPlainListStyle,GroupedListStyleoInsetGroupedListStyle. - Gestión de Memoria Automática: Las listas en SwiftUI son inherentemente “perezosas” (lazy). Solo renderizan en memoria las vistas que están visibles en la pantalla (y un pequeño buffer por encima y por debajo).
- Funcionalidades “Out-of-the-box”: Soporta de forma nativa acciones de deslizamiento (
.swipeActions), modo de edición para reordenar o eliminar filas (.onDelete,.onMove), y recarga tirando hacia abajo (.refreshable).
Ejemplo de código con List en Swift
import SwiftUI
struct Contact: Identifiable {
let id = UUID()
let name: String
}
struct ContactListView: View {
@State private var contacts = [
Contact(name: "Ana"), Contact(name: "Carlos"), Contact(name: "Elena")
]
var body: some View {
NavigationView {
List {
ForEach(contacts) { contact in
Text(contact.name)
.swipeActions(edge: .trailing) {
Button(role: .destructive) {
// Acción de borrar
} label: {
Label("Borrar", systemImage: "trash")
}
}
}
}
.navigationTitle("Contactos")
.refreshable {
// Lógica para recargar datos
}
}
}
}
Como puedes observar en este código de Swift, con apenas unas líneas hemos implementado una lista con swipe to delete y pull to refresh. Esta es la magia de la List.
¿Qué es un LazyVStack en SwiftUI?
Introducido en iOS 14, el LazyVStack (Lazy Vertical Stack) nació para solucionar los problemas de rendimiento del VStack tradicional al manejar grandes cantidades de datos, y la rigidez de diseño de la List.
Mientras que un VStack normal instancia y renderiza todos sus elementos hijos inmediatamente (lo cual colapsaría la memoria si tienes 10,000 elementos), un LazyVStack hace honor a su nombre: crea los elementos solo a medida que necesitan aparecer en pantalla.
A diferencia de la List, el LazyVStack es un lienzo completamente en blanco. No proporciona scroll por sí mismo (debes envolverlo en un ScrollView), no tiene separadores, no tiene márgenes predeterminados y no incluye comportamientos nativos como el swipe to delete.
Características Principales del LazyVStack
- Rendimiento Optimizado a Medida: Renderiza vistas bajo demanda, siendo ideal para feeds de datos infinitos.
- Control Total del Diseño: Al no imponer estilos del sistema, puedes crear interfaces completamente a medida, tarjetas (cards), o cuadrículas complejas.
- Comportamiento Modular: Funciona en conjunto con un
ScrollView, lo que te permite decidir exactamente cómo y dónde se hace el scroll, e incluso añadir elementos estáticos dentro del mismo scroll que no formen parte de la pila perezosa.
Ejemplo de código con LazyVStack en Swift
import SwiftUI
struct FeedView: View {
let items = Array(1...1000)
var body: some View {
ScrollView {
LazyVStack(spacing: 16, pinnedViews: [.sectionHeaders]) {
Section(header: Text("Mi Feed Personalizado").font(.headline).background(Color.white)) {
ForEach(items, id: \.self) { item in
VStack(alignment: .leading) {
Text("Publicación #\(item)")
.font(.title3)
.fontWeight(.bold)
Text("Este es un diseño completamente personalizado que no sigue las reglas de una List estándar.")
.foregroundColor(.secondary)
}
.padding()
.frame(maxWidth: .infinity, alignment: .leading)
.background(Color.blue.opacity(0.1))
.cornerRadius(12)
.padding(.horizontal)
}
}
}
}
}
}
En este escenario en Xcode, hemos creado un diseño de tarjetas que sería muy tedioso de replicar dentro de una List debido a los estilos que esta impone por defecto.
Analizando el Comportamiento bajo el Capó
Para un iOS Developer senior, la diferencia real radica en cómo el framework gestiona el ciclo de vida de las vistas.
Cuando usas una List, SwiftUI optimiza enormemente el reciclaje de celdas a nivel de sistema operativo. Sin embargo, la List a veces puede ser impredecible con el estado interno de sus filas si estas son muy complejas.
El LazyVStack, por otro lado, llama a .onAppear y .onDisappear de forma mucho más estricta a medida que el usuario hace scroll. Esto lo hace ideal para disparar llamadas de red asíncronas (como cargar la siguiente página de una API) justamente cuando el usuario llega al final de la pila.
Nota de rendimiento: Aunque
LazyVStackes eficiente, si las vistas que contiene son computacionalmente pesadas de inicializar, puedes notar pequeños “tirones” al hacer scroll rápido. LaListsuele gestionar el scroll ultra-rápido un poco mejor gracias a la herencia de UIKit subyacente.
Tabla Comparativa: List vs LazyVStack
A continuación, presentamos una tabla resumen para que tengas una referencia rápida en tu día a día con programación Swift:
| Característica | List | LazyVStack (+ ScrollView) |
|---|---|---|
| Diseño por defecto | Estilos del sistema de Apple (separadores, márgenes). | Ninguno. Lienzo en blanco total. |
| Scroll Integrado | Sí, no necesita ScrollView. | No, debe estar dentro de un ScrollView. |
| Swipe Actions (Deslizar) | Nativo (con modificador .swipeActions). | No soportado nativamente (requiere código complejo). |
| Pull to Refresh | Nativo (con modificador .refreshable). | Nativo en iOS 15+ aplicando al ScrollView. |
| Modo Edición / Reordenar | Nativo (con EditButton y .onMove). | No soportado nativamente. |
| Separadores de fila | Automáticos (se pueden ocultar con listRowSeparator). | Manuales (debes dibujar un Divider tú mismo). |
| Rendimiento en listas enormes | Excelente (reciclaje de celdas optimizado). | Muy bueno (instanciación bajo demanda). |
| Flexibilidad UI | Rígida. Cuesta sobrescribir fondos y márgenes. | Absoluta. Eres dueño de cada píxel. |
Cuándo usar cada componente en el Desarrollo de Apps
La decisión entre List vs LazyVStack en SwiftUI debe basarse puramente en los requisitos de experiencia de usuario y diseño de tu aplicación.
Debes usar List cuando:
- Estás construyendo pantallas de configuración o ajustes. (Ejemplo: la app de Ajustes de iOS). El estilo
.listStyle(.insetGrouped)está pensado exactamente para esto. - Necesitas interacciones estándar del sistema. Si tu app requiere que el usuario deslice para borrar, reordene elementos arrastrándolos o seleccione múltiples filas, la
Listte ahorrará cientos de líneas de código y dolores de cabeza. - El diseño dicta un “Look and Feel” nativo de Apple. Muchos usuarios prefieren la familiaridad de los componentes nativos. Si no tienes un equipo de diseño empujando por una interfaz radicalmente distinta, ve por la
List.
Debes usar LazyVStack cuando:
- El diseño es completamente a medida. Si tienes diseños de Figma o Sketch con tarjetas con sombras complejas, sangrías asimétricas, o fondos dinámicos sin separadores de línea, luchar contra la
Listserá frustrante. ElLazyVStackte da la libertad total. - Tienes un feed de contenido estilo red social. Piensa en Instagram o Twitter. Estos no son “listas” en el sentido de la app Ajustes; son flujos continuos de contenido variado. Un
LazyVStackdentro de unScrollViewes la arquitectura estándar para esto. - Necesitas secciones con scroll horizontal dentro del scroll vertical. Combinar un
LazyVStackvertical que a su vez contieneScrollView(.horizontal)(con unLazyHStack) funciona infinitamente mejor y con menos bugs de layout que intentar encajar esto dentro de las celdas de unaList.
Consideraciones Multiplataforma (iOS, macOS, watchOS)
Una de las grandes ventajas de SwiftUI es su portabilidad en el ecosistema de Apple. Sin embargo, el comportamiento de estos componentes varía según el dispositivo.
En iOS y iPadOS
En iPadOS, la List brilla especialmente cuando se usa en arquitecturas de navegación lateral (NavigationSplitView). Si aplicas un .listStyle(.sidebar), SwiftUI transformará automáticamente tu lista en una barra lateral de navegación con estilo traslúcido y comportamiento colapsable nativo. Intentar replicar un sidebar de iPadOS con un LazyVStack es una pérdida de tiempo.
En macOS
En el desarrollo para Mac utilizando Xcode, las listas adquieren comportamientos de selección de escritorio. Una List en macOS soporta la selección de múltiples filas usando la tecla Shift o Command de forma nativa. Además, los estilos de tabla (.listStyle(.inset)) adoptan la estética de macOS (como Finder o Mail). El LazyVStack, por otro lado, sigue siendo útil para galerías o grids personalizados, pero pierde todas las funcionalidades de accesibilidad de escritorio que te regala la List.
En watchOS
El Apple Watch tiene recursos extremadamente limitados. En watchOS, la List es casi obligatoria para cualquier menú o navegación principal. SwiftUI optimiza las listas en el reloj para que interactúen a la perfección con la Digital Crown (Corona Digital). Aunque puedes usar un ScrollView con un LazyVStack, el sistema operativo maneja el focus y la retroalimentación háptica mucho mejor cuando utilizas una List estándar.
Reflexión Final para el iOS Developer
A medida que avances en tu carrera de programación Swift, te darás cuenta de que no existe una bala de plata. El dilema de List vs LazyVStack en SwiftUI no se trata de cuál es mejor, sino de cuál es la herramienta adecuada para el trabajo específico.
Como regla general, adopta un enfoque pragmático: Empieza siempre con una List. Te proporcionará accesibilidad, rendimiento y un comportamiento esperado por el usuario “gratis”. Solo cuando los requisitos de diseño de tu aplicación (UI/UX) comiencen a chocar violentamente contra las restricciones de la List (y te encuentres peleando con modificadores como .listRowInsets, .listRowBackground, etc.), es el momento de refactorizar tu código y migrar hacia un ScrollView combinado con un LazyVStack.








