SwiftUI Series 10 | Carga asincrónica de SwiftUI: tarea, asíncrono/espera y vinculación de estado de interfaz
Lo realmente difícil es mantener consistentes la carga, los resultados, los errores y el ciclo de vida de la página.
Una vez que se cargan muchas páginas SwiftUI de forma asincrónica, los problemas comienzan a aumentar:
onAppearrepetirá la solicitud- El estado de carga es inestable.
- Los resultados antiguos cambiarán la página actual
- La tarea todavía se está reescribiendo después de salir de la página.
Estos problemas pueden parecerse a los problemas de Task o async/await en la superficie, pero las razones más fundamentales suelen ser:
El ciclo de vida de la tarea asincrónica y el ciclo de vida del estado de la página no están alineados.
Entonces lo que realmente tenemos que afrontar es:
- ¿Cuándo comienza la solicitud?
- ¿Seré elegible para cambiar la página después de que aparezcan los resultados?
- ¿Cuándo deberían caducar las tareas antiguas?
- ¿Cómo se excluyen mutuamente estos estados de carga/error/contenido?
1. El error más fácil es considerar la página asincrónica como “una solicitud + un valor booleano”
Inicialmente, muchas páginas se escribirán así:
- A
isLoading - A
items - A
errorMessage
Añade otro:
Task {
await load()
}
Por supuesto que funcionará al principio, pero tan pronto como la página comience a admitir:
- inténtalo de nuevo
- Tire hacia abajo para actualizar
- Buscar
- Conmutación condicional
Los problemas surgirán uno tras otro. Porque la página real es un conjunto de tareas que pueden reemplazarse y cubrirse entre sí.
2. El verdadero núcleo de las páginas asincrónicas radica en el flujo de estado.
Si solo entiende la carga asincrónica como “recuperar datos”, será fácil ignorar que lo que realmente le importa a la página son estos estados:
- Cargando al entrar por primera vez
- Actualizar según el contenido existente
- Reintentar después de una carga fallida
- Solicitud después de que ciertas condiciones cambien
Ambas son “cargas”, pero no son lo mismo en la semántica de la página.
Si todo está representado por un solo isLoading, la página pronto se volverá desordenada.
Entonces una idea más práctica suele ser:
- Primero defina en qué estado semántico se encuentra actualmente la página.
- Deje que la tarea asincrónica impulse este cambio de flujo de estado.
3. onAppear + Task a menudo se vuelve más peligroso cuanto más lo escribes.
Porque es muy fácil.
Una situación común es escribir naturalmente:
.onAppear {
Task {
await viewModel.load()
}
}
Este código en sí no es necesariamente incorrecto, pero el peligro es que es demasiado fácil establecer de forma predeterminada:
- La página aparece una vez.
- Solicitud de envío una vez
- Cambiar el estado una vez después de regresar
En proyectos reales, estos tres supuestos pueden no ser ciertos.
Por lo tanto, la clave para saber si la carga asincrónica es realmente estable no es si existe Task, sino más bien:
- Si tareas similares se gestionan de manera uniforme -Si las tareas antiguas se cancelarán o caducarán
- Si es necesario verificar el resultado en el contexto actual.
4. Un malentendido común: si el resultado es exitoso, accederá directamente a la página.
Muchas páginas están en estado desordenado y la causa raíz está aquí.
Por ejemplo:
- Las palabras clave han cambiado
- Las solicitudes antiguas vuelven más tarde.
- Los resultados antiguos aún cambian la página.
Desde la perspectiva de la solicitud, no falló, pero desde la perspectiva de la página expiró.
Entonces, una cosa muy importante en las páginas asincrónicas es:
No todos los resultados devueltos exitosamente son automáticamente elegibles para reescribir la interfaz de usuario actual.
Por lo tanto, la carga asincrónica de páginas generalmente no solo puede mirar “si se obtiene el resultado”, sino que también debe mirar “si el resultado sigue siendo válido ahora”.
5. Una dirección más estable: cierre la tarea de carga en lugar de permitir que cada evento de la interfaz de usuario envíe su propia solicitud
Si una página admite:
- carga inicial
- inténtalo de nuevo
- actualizar
- Cambios de filtro
El enfoque más estable suele ser agrupar tareas similares.
Por ejemplo:
- Todas las entradas finalmente llaman al mismo
reload() - La tarea actualmente activa está en manos de ViewModel.
- Cuando aparecen nuevas tareas, las tareas antiguas se cancelan o se consideran inválidas.
De esta manera, al menos será más fácil mantener la coherencia del estado de la página porque:
- Está claro quién está cargando.
- También está claro quién puede finalizar la carga.
6. Conclusión: Lo que realmente debe abordar la carga asincrónica de SwiftUI es si la tarea y el estado de la página se pueden explicar claramente.
Para decirlo en forma más breve, diría:
Cuando se trata de carga asincrónica en SwiftUI, la verdadera dificultad es mantener consistente el ciclo de vida de la tarea, la validez de los resultados y el flujo del estado de la página.
Mientras no se establezcan estas tres cosas la página seguirá creciendo:
- Repetir solicitud
- Vuelve a escribir resultados antiguos
- confusión de carga
Por lo general, estos problemas no se pueden solucionar escribiendo algunos Task más.
What to read next
Want more posts about SwiftUI?
Posts in the same category are usually the best next step for reading more on this topic.
View same categoryWant to keep following #iOS?
Tags are useful for related tools, specific problems, and similar troubleshooting notes.
View same tagWant to explore another direction?
If you are not sure what to read next, return to the homepage and start from categories, topics, or latest updates.
Back home