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
Viendo ahora - 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
21:54 min
MVVM y Clean Architecture
Marcar tareas completadas en SwiftUI
Resumen
Marcar una tarea como completada es la acción que cierra el ciclo de cualquier app de pendientes. Aquí aprendes a construir un TodoStatusView en SwiftUI que alterna entre un círculo vacío y un checkmark, conectarlo al ViewModel y reutilizarlo en el listado, el detalle y los archivados. Va dirigido a quien ya tiene una app de to dos funcional y solo le falta esta última pieza.
Cómo crear el TodoStatusView desde cero en SwiftUI
La idea es simple: una vista pequeña en la esquina superior derecha del ítem que muestre si la tarea está hecha o no. Tú creas el archivo TodoStatusView manualmente y armas su estructura básica para luego conectarla al modelo.
Dentro de la vista necesitas tres piezas clave que se conectan con el resto de la app [05:30]:
- Una referencia al ViewModel con
@EnvironmentObjectpara acceder a las funciones globales. - Una variable pública
todode tipoTodoEntityque recibe la tarea desde afuera. - Una variable
disabledde tipo Bool que controla si el usuario puede o no tocar el ícono.
En el init inicializas el todo con un TodoEntity y el parámetro disabled arranca en false. Esto te deja preparada la vista para recibir cualquier tarea del listado.
¿Qué hace EnvironmentObject en SwiftUI? Te permite compartir un objeto observable, como tu ViewModel, entre varias vistas sin pasarlo manualmente por cada inicializador.
Cómo alternar el estado isComplete con la función toggle
En el ViewModel tienes la función updateTodoStatus, y aquí ocurre la magia. Primero obtienes el índice del to do con getTodoIndex. Si no lo encuentra, sales con un return. Si lo encuentra, accedes a la colección por ese índice y modificas la propiedad isComplete.
En lugar de escribir un if/else para invertir el booleano, usas la función nativa toggle() [02:45]. Si está en true, lo pasa a false; si está en false, lo pasa a true. Después llamas a la función que guarda los datos y listo.
¿Para qué sirve toggle en una variable booleana? Invierte automáticamente su valor sin necesidad de comparar. Reduce el código a una sola línea y evita errores de lógica.
Cómo elegir el ícono según isComplete
Dentro del body de TodoStatusView defines una variable imageName de tipo String usando un operador ternario sobre todo.isComplete:
- Si la tarea está completa, usas
checkmark.circle.fill. - Si no lo está, usas
circle, que es un círculo vacío del sistema.
Ambos íconos vienen de SF Symbols, así que no necesitas importar recursos externos. Después agregas variables width y height de tipo CGFloat para controlar el tamaño, normalmente 24 unidades para el círculo vacío y un poco menos para el checkmark lleno.
La imagen final la retornas con Image(systemName: imageName), le aplicas .resizable() y un .frame(width: width, height: height) para que respete el tamaño definido.
Dónde mostrar el TodoStatusView en la app
Esta vista no vive sola. La idea es reutilizarla en tres lugares distintos según el contexto.
Cómo integrarlo en TodoItemView y el preview
En TodoItemView, justo después del Spacer (alrededor de la línea 28 o 29), agregas TodoStatusView(todo: todo). El Spacer empuja el ícono a la esquina derecha, que es exactamente donde lo quieres visualmente [10:15].
En TodoPreviewView, que es la pantalla de detalle, lo colocas después del bloque de fecha y título, antes del detalle. Si aparece centrado, mueves la llamada después del Spacer para que se alinee a la derecha.
Cómo agregar el evento de toque con onTapGesture
Para que el ícono responda al tap, dentro de TodoStatusView agregas el modificador .onTapGesture y llamas a viewModel.updateTodoStatus(todo). Justo después encadenas .disabled(disabled) para que, cuando esa propiedad sea true, el gesto se ignore.
Esto te da control total: en el listado activo el usuario puede marcar y desmarcar, pero en otras vistas puedes bloquearlo pasando disabled: true.
Cómo mostrar el estado en tareas archivadas sin permitir edición
Las tareas archivadas también deberían mostrar si están completadas, pero sin que el usuario pueda cambiarlas. Aquí entra TodoArchiveItemView.
Reestructuras la vista creando un VStack con alineación .leading y, dentro, un HStack con alineación .center. El orden visual queda así:
- Primero el
TodoStatusView(todo: todo)con el modificador.disabled(true). - Después el título con
font: .headlineylineLimit(1). - Debajo, la fecha usando
Text(todo.date, format: .dateTime)mostrando día, mes y año.
El resultado es una fila clara: ves el estado, el título y la fecha en una sola mirada, pero el ícono no responde al tap porque disabled está en true. Esa es la utilidad real de haber expuesto esa propiedad desde el inicio.
Con esto, la variable isComplete viaja por toda la app y su único trabajo es alternar entre true y false. ¿Tú dónde más lo aplicarías en tu propia app de tareas? Cuéntame en los comentarios.