ProgramaciónDesarrollador móvil

Explique la esencia del trabajo de GCD (Grand Central Dispatch) y DispatchQueue en Swift, cómo crear correctamente código asíncrono y qué trampas se pueden encontrar al trabajar con multihilos.

Supere entrevistas con el asistente de IA Hintsage

Respuesta.

Historia de la pregunta

Grand Central Dispatch (GCD) llegó a iOS y macOS en 2009 como un sistema de bajo nivel para organizar código concurrente y asíncrono (multihilos), basado en colas: DispatchQueue. GCD resultó ser mucho más conciso que la gestión manual de hilos, proporcionando una ejecución segura de tareas, sincronización y una API conveniente.

Problema

La asincronía y la multihilo han sido tradicionalmente la fuente de la mayoría de los problemas: condiciones de carrera, bloqueos, bloqueos vivos de la interfaz y fallos complejos. El uso incorrecto de colas o intentar acceder a la UI desde un hilo que no es el principal provoca errores.

Solución

Swift permite crear fácilmente trabajos en segundo plano y regresar de manera segura al hilo principal para actualizar la interfaz mediante colas globales y personalizadas. Utilice DispatchQueue para el trabajo asíncrono y DispatchGroup si necesita esperar a que se complete un conjunto de tareas asíncronas.

Ejemplo de código:

let backgroundQueue = DispatchQueue(label: "background", qos: .background) backgroundQueue.async { // se ejecuta en un hilo de fondo let image = downloadImage() DispatchQueue.main.async { // actualización segura de la UI imageView.image = image } }

Características clave:

  • DispatchQueue.async ejecuta el bloque de forma asíncrona
  • DispatchQueue.main.async para llamar en el hilo principal
  • DispatchSemaphore, DispatchGroup, sync, así como qos para controlar la prioridad de las tareas

Preguntas capciosas.

¿Qué sucede si llamo a sync en la cola principal desde el hilo principal?

Ocurrirá un deadlock: el hilo principal espera la ejecución de una tarea en sí mismo, y la aplicación "se congelará".

DispatchQueue.main.sync { // DEADLOCK }

¿Puede DispatchQueue.serial ejecutar tareas en paralelo?

No, la cola serial siempre ejecuta tareas una a la vez, sin embargo, si se crean varias colas seriales, se ejecutan en paralelo entre sí.

¿Está permitido actualizar la interfaz no desde el hilo principal?

No, cualquier manipulación con UIKit (o renderizado de SwiftUI View) solo se puede hacer desde DispatchQueue.main. Violaciones llevarán a un funcionamiento inestable y fallos.

Errores típicos y anti-patrones

  • Llamada síncrona en el hilo principal (deadlock)
  • Intento de actualizar la UI desde el fondo
  • Carrera de recursos no controlada al escribir en variables compartidas
  • Uso de colas globales sin necesidad, falta de colas dedicadas

Ejemplo de la vida real

Caso negativo

En el hilo de fondo se cargan datos, actualizan la UI de inmediato: la aplicación a veces falla o la interfaz se congela. Además, utilizan un estado mutable compartido entre hilos sin sincronización.

Ventajas:

  • Código visualmente conciso

Desventajas:

  • Errores inestables y fallos poco reproducibles
  • Pérdidas en rendimiento

Caso positivo

Organización de todas las actualizaciones de UI solo en DispatchQueue.main, colas dedicadas para trabajar con grandes datos, uso de DispatchGroup para controlar la finalización de tareas asíncronas.

Ventajas:

  • Sin carreras
  • División efectiva del trabajo entre hilos
  • Fácil de mantener

Desventajas:

  • Muchos "cambios de hilo", se requiere disciplina al trabajar con recursos compartidos