dispatch_after en Swift: GCD bajo el capó — análisis con ejemplos

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

dispatch_after en Swift: cómo GCD ejecuta tareas retrasadas bajo el capó



Imagina: estás escribiendo una aplicación en Swift y necesitas ejecutar un fragmento de código no de inmediato, sino, digamos, después de 3 segundos. Lo primero que viene a la mente es dispatch_after. Pero si miras versiones antiguas de Swift o Stack Overflow, verás que este método ha cambiado. Y lo principal es que pocos entienden lo que realmente sucede dentro de Grand Central Dispatch (GCD) cuando decimos: «Haz esto en 2 segundos».



En este artículo no solo mostraremos cómo escribir dispatch_after en Swift moderno. Nos meteremos bajo el capó de GCD, analizaremos colas, hilos y temporizadores para que puedas escribir código asíncrono robusto y eficiente. ¡Allá vamos!



¿Qué es dispatch_after y por qué se convirtió en asyncAfter?



En versiones antiguas de Swift (1.x, 2.x) podías encontrarte con este código:



dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(2 * NSEC_PER_SEC)), dispatch_get_main_queue()) {    print("Han pasado 2 segundos")}


Este código funcionaba, pero se veía voluminoso. A partir de Swift 3, Apple realizó una refactorización de toda la API de GCD, haciéndola más «swiftiana». Ahora la misma funcionalidad se ve así:



DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {    print("Han pasado 2 segundos")}


Observa: asyncAfter es un método de la cola (DispatchQueue), no una función independiente. Este es un cambio clave: ahora indicas explícitamente en qué cola ejecutar la tarea.



Cómo funciona GCD bajo el capó: colas, hilos y temporizadores



Para entender dispatch_after (o asyncAfter), necesitas comprender tres entidades:



  • DispatchQueue — cola de tareas. Puede ser serial o concurrente.
  • DispatchWorkItem — la tarea que colocas en la cola. En nuestro caso, es un closure.
  • DispatchTime — el momento en el que la tarea debe ejecutarse. GCD utiliza un temporizador del sistema para rastrear los plazos.


Cuando llamas a asyncAfter, GCD no crea un nuevo hilo. En su lugar:



  1. Crea un temporizador que se activará en el momento especificado.
  2. Coloca la tarea en una cola especial de tareas retrasadas (a menudo llamada dispatch timer).
  3. Cuando el temporizador se activa, GCD mueve la tarea a la cola DispatchQueue normal, donde espera su hilo.


Si la cola en la que colocas la tarea está ocupada con otras tareas, tu tarea retrasada puede ejecutarse después del plazo especificado. Este es un punto importante: dispatch_after garantiza que la tarea no se ejecutará antes del plazo, pero puede ejecutarse después.



Ejemplo práctico: dispatch_after para actualizar la UI



El escenario más común es actualizar la interfaz después de un tiempo tras la acción del usuario. Supongamos que muestras un mensaje «Guardado» y después de 2 segundos lo eliminas:



func showTemporaryMessage() {    let messageLabel = UILabel()    messageLabel.text = "¡Guardado!"    messageLabel.alpha = 1.0    view.addSubview(messageLabel)

DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) { UIView.animate(withDuration: 0.5) { messageLabel.alpha = 0.0 } completion: { _ in messageLabel.removeFromSuperview() } }}


Observa: usamos DispatchQueue.main porque todas las operaciones con la UI deben ejecutarse en el hilo principal. Si hubiéramos llamado a asyncAfter en una cola en segundo plano y luego intentado modificar la UI, la aplicación se habría bloqueado.



Trampas de dispatch_after: fugas de memoria y captura de self



Uno de los errores más comunes es una referencia fuerte a self den

Blogs

Book Recommendations