Contenido del curso
Estructura de un Proyecto con MVVM
Operaciones CRUD en un proyecto con MVVM
- 11

Función addTodo con Core Data en SwiftUI
19:47 min - 12

Funcionalidades básicas para gestionar tareas en SwiftUI
14:30 min - 13

Listado y detalle de notas en SwiftUI
22:35 min - 14

Editar todos con SwiftUI y Core Data
13:41 min - 15

Archivar tareas en SwiftUI con Core Data
15:28 min - 16

Cómo desarchivar tareas con unarchiveTodo
03:25 min - 17

Eliminar un to do definitivamente con Core Data
04:15 min - 18

Marcar tareas completadas en SwiftUI
20:50 min - 19

Creación de Vistas Amigables en SwiftUI para Aplicaciones de Tareas
19:52 min
Clean Architecture
- 20

Qué es Clean Architecture y por qué supera a MVVM
05:52 min - 21

Estructura y Ventajas de la Clean Architecture
03:47 min - 22

Estructura de proyecto iOS con Clean Architecture
06:01 min - 23

Mapeo de JSON a structs Swift con Codable
09:10 min - 24

Capa de datos con Clean Architecture en Swift
30:54 min - 25

Casos de uso en la capa de dominio Swift
09:35 min - 26

Capa de presentación con MVVM en SwiftUI
15:37 min - 27

Navegación y detalle con Clean Architecture en SwiftUI
Viendo ahora
MVVM y Clean Architecture
Navegación y detalle con Clean Architecture en SwiftUI
Resumen
Construir una pantalla de detalle en SwiftUI requiere combinar navegación, ViewModel y casos de uso bajo Clean Architecture para mantener separadas las responsabilidades entre datos, dominio y presentación. Aquí ves cómo conectar el listado de programas de televisión con su vista de detalle, paso a paso, usando NavigationLink, StateObject y funciones asíncronas.
¿Cómo se navega entre vistas en SwiftUI?
La navegación en SwiftUI se construye con dos piezas que trabajan juntas: un contenedor que habilita el flujo y un enlace que define el destino.
Dentro del archivo PopularShowView reemplazas el simple texto de cada item por un NavigationLink. Este componente necesita un destination (la vista a la que vas) y un label (lo que se muestra en pantalla). El destino será una nueva vista llamada DetailView, que creas desde un template de SwiftUI [04:10].
¿Qué hace NavigationLink en SwiftUI? Es el componente que conecta una vista con otra. Recibe un destino y muestra un elemento clickeable que dispara la navegación cuando el usuario lo toca.
Para que la navegación funcione, toda la lista debe estar envuelta en un NavigationView. Si lo olvidas, el clic no dispara ninguna transición. Cortas el contenido de List junto con su onAppear, creas un NavigationView como vista principal y pegas todo dentro [18:30].
¿Cómo se estructura el ViewModel del detalle?
El ViewModel actúa como puente entre la vista y los casos de uso del dominio. Aquí cargas los datos asíncronos y los expones a la UI.
Creas la clase TVShowDetailsViewModel marcada como final y conforme a ObservableObject. Dentro defines:
- Una propiedad
@Published var details: TVShowDetails?que puede ser nula cuando aún no llegan los datos. - Una propiedad
@Published var showIDinicializada en cero para guardar el identificador del programa. - Una propiedad privada
getTVShowDetailsUseCasecon el tipo del protocol, no de la implementación concreta.
El init recibe el identificador entero y la dependencia del caso de uso. Esa inyección de dependencias por protocolo es lo que permite cambiar la implementación sin tocar el ViewModel, algo clave para testing [08:45].
¿Cómo se carga la información de forma asíncrona?
La función loadDetails(id: Int) se marca como async y usa un bloque do/catch para capturar errores. Dentro ejecutas:
try await getTVShowDetailsUseCase.execute(id)para obtener los datos del dominio.await MainActor.run { self.details = detalles }para actualizar la propiedad publicada en el hilo principal.- Un
print(error)en elcatchpara registrar fallos.
¿Por qué usar MainActor.run al actualizar @Published? Porque las propiedades observadas por la UI deben modificarse en el hilo principal. MainActor garantiza que SwiftUI reciba el cambio sin condiciones de carrera.
¿Cómo se conecta el ViewModel con DetailView?
En DetailView declaras el ViewModel con @StateObject private var viewModel: TVShowDetailsViewModel. Como el detalle no cambia durante la vida de la vista, el init recibe el ViewModel ya construido y lo asigna usando el guion bajo (_viewModel = StateObject(wrappedValue: viewModel)).
Esto significa que cuando PopularShowView crea el NavigationLink, debe pasar el ViewModel inicializado con el identificador del show:
swift NavigationLink(destination: DetailView(viewModel: TVShowDetailsViewModel(id: show.id))) { Text(show.name) }
Si olvidas pasar el ViewModel, el compilador marca un error porque el init lo exige [16:20].
¿Cómo se diseña el cuerpo de la vista de detalle?
Dentro de un VStack usas un if let details = viewModel.details para distinguir entre estado de carga y datos disponibles:
- Si
detailsexiste, muestras unText(details.name)con fuente headline y padding inferior de 20 unidades, eloverviewcomo resumen, y los géneros si la colección no está vacía. - Si aún no llega, muestras
Text("Cargando...")junto con unProgressView()con.progressViewStyle(.circular).
Para iterar los géneros con ForEach, la estructura Genre debe conformar el protocolo Identifiable. Sin un identificador, SwiftUI no sabe distinguir cada elemento de la colección y arroja un error de compilación [14:50].
El VStack se conecta con .onAppear, que dispara un Task { await viewModel.loadDetails(id: viewModel.showID) }. Envolver la llamada en un Task es necesario porque onAppear es síncrono y loadDetails es async.
¿Por qué Clean Architecture ordena mejor el proyecto?
La aplicación final navega desde la lista de programas populares hacia el detalle de cada serie, mostrando nombre, resumen y géneros como Comedia, Drama o Familia. Pero lo valioso no es la pantalla, sino cómo se separan las responsabilidades.
El proyecto se divide en tres capas que reflejan el diagrama de Clean Architecture, de adentro hacia afuera:
- Datos: modelos, endpoints, decodificación con
JSONDecodery la implementación del repositorio que se comunica con la red. - Dominio: casos de uso como
GetTVShowDetailsUseCase, que representan acciones específicas de la aplicación y conectan con la capa de datos a través de protocolos. - Presentación: vistas SwiftUI y ViewModels que consumen los casos de uso y exponen estado observable.
Este orden facilita agregar funciones nuevas, modificar comportamientos existentes y, sobre todo, escribir tests unitarios sin acoplar la UI a la red. MVVM por sí solo separa vista y lógica, pero combinarlo con Clean Architecture te da un nivel adicional de organización que escala mejor cuando el proyecto crece.
¿Ya probaste estructurar tu próxima app iOS con esta separación de capas? Cuéntame en los comentarios qué parte te resultó más útil al implementarla.