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
Viendo ahora - 26

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

Navegación y detalle con Clean Architecture en SwiftUI
21:54 min
MVVM y Clean Architecture
Casos de uso en la capa de dominio Swift
Resumen
Definir casos de uso en la capa de dominio te permite separar el comportamiento de tu aplicación iOS de la lógica de datos, siguiendo Clean Architecture. Aquí aprendes a crear use cases en Swift para consumir un API de programas de televisión, aplicando inyección de dependencias y el principio de inversión.
Qué es un caso de uso y por qué va en la capa de dominio
Un caso de uso describe una acción concreta que tu aplicación puede ejecutar. No mezcla detalles de red ni de almacenamiento; solo orquesta la lógica de negocio.
En la app que estamos construyendo, hay dos comportamientos claros: obtener el listado de programas populares y obtener el detalle de uno específico. Cada uno se traduce en un archivo separado dentro de la capa de dominio.
¿Qué es un caso de uso en Clean Architecture? Es una clase que representa una acción única de la aplicación, como obtener programas populares. Vive en la capa de dominio y delega la obtención de datos al repositorio.
Cómo defino el protocolo de un Use Case en Swift
El primer archivo se llama GetPopularTVShowsUseCaseProtocol [01:25]. Dentro declaras un protocol con el mismo nombre y una función asíncrona que retorna un arreglo de TVShow.
swift protocol GetPopularTVShowsUseCaseProtocol { func execute() async throws -> [TVShow] }
Esta declaración no implementa nada. Solo define el contrato: una función execute marcada como async throws que devuelve [TVShow]. Así cualquier clase que adopte el protocolo sabe qué firma debe respetar.
Cómo implemento el caso de uso con inyección de dependencias
La implementación vive en la misma capa, pero como una final class que adopta el protocolo. Aquí aplicas el principio de inversión de dependencias: la clase depende de la abstracción TVShowRepository, no de su implementación concreta.
swift final class GetPopularTVShowsUseCase: GetPopularTVShowsUseCaseProtocol { private let repository: TVShowRepository
init(repository: TVShowRepository = TVShowRepositoryImpl()) { self.repository = repository } func execute() async throws -> [TVShow] { try await repository.fetchPopularTVShows() }
}
Fíjate en el detalle del init: el parámetro recibe un TVShowRepository (el protocolo) y por defecto se le asigna una instancia de TVShowRepositoryImpl. Esto te permite inyectar mocks en pruebas sin tocar la lógica.
¿Por qué inyectar el repositorio en lugar de instanciarlo dentro? Porque te da control sobre la dependencia. Puedes sustituirla por una versión falsa al testear, sin que la clase sepa de la implementación real.
Qué cuidados hay con el nombre execute
Un error común es declarar execute en el protocolo y escribir executes en la clase, o al revés. Swift no detectará el método como implementación del protocolo y lanzará error de compilación [05:30]. Revisa que ambos nombres coincidan exactamente.
Cómo creo el caso de uso para el detalle de un programa
El segundo archivo, GetTVShowDetailsUseCaseProtocol, sigue la misma estructura, pero la función execute recibe un identificador entero y devuelve un objeto TVShowDetails.
swift protocol GetTVShowDetailsUseCaseProtocol { func execute(id: Int) async throws -> TVShowDetails }
final class GetTVShowDetailsUseCase: GetTVShowDetailsUseCaseProtocol { private let repository: TVShowRepository
init(repository: TVShowRepository = TVShowRepositoryImpl()) { self.repository = repository } func execute(id: Int) async throws -> TVShowDetails { try await repository.fetchTVShowDetails(id: id) }
}
La diferencia clave es el parámetro id: Int que viaja desde la vista hasta el repositorio, atravesando el caso de uso sin transformaciones. El use case actúa como puente delgado.
¿Qué hace el método execute en un Use Case? Llama al repositorio correspondiente y retorna el resultado. No procesa datos ni maneja red; solo orquesta la acción.
Qué responsabilidades quedan separadas entre capas
Con estos dos archivos, la capa de dominio queda lista. La división de responsabilidades es:
- La capa de datos maneja la comunicación con el API y el mapeo de modelos.
- La capa de dominio expone casos de uso y depende solo de abstracciones.
- La capa de presentación, que sigue pendiente, consumirá estos use cases desde las vistas o view models.
Esta separación te permite cambiar la fuente de datos sin tocar el dominio, y modificar la lógica de negocio sin alterar la UI.
¿Tú cómo estás organizando tus use cases en proyectos Swift? Cuéntame en los comentarios si prefieres una clase por acción o agrupar varias en un solo archivo.