Concurrencia y multihilo en Swift: guía completa

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

Introducción a la concurrencia y el multihilo en Swift



Las aplicaciones modernas para iOS y macOS deben ser rápidas y receptivas. El usuario no debe esperar mientras se carga una imagen o se realiza un cálculo complejo. Para ello, Swift dispone de mecanismos de concurrencia y multihilo. En este artículo, analizaremos los conceptos clave, desde el clásico Grand Central Dispatch (GCD) hasta el moderno async/await de Swift Concurrency.



La concurrencia (concurrency) es la capacidad de un programa para ejecutar múltiples tareas simultáneamente, alternando entre ellas. El multihilo (multithreading) es una implementación de la concurrencia donde las tareas se ejecutan en diferentes hilos del sistema operativo. Swift proporciona herramientas potentes y seguras para trabajar con estos conceptos.



1. Grand Central Dispatch (GCD) — la base del multihilo



Grand Central Dispatch (GCD) es una biblioteca de bajo nivel de Apple para gestionar la ejecución paralela de código. Funciona basándose en colas (dispatch queues).



Tipos de colas en GCD

  • Serial Queue (cola serial) — las tareas se ejecutan una tras otra en el orden en que se añaden.
  • Concurrent Queue (cola concurrente) — las tareas pueden ejecutarse simultáneamente en diferentes hilos.
  • Main Queue (cola principal) — ejecuta tareas en el hilo principal, destinada a actualizar la UI.
  • Global Queues (colas globales) — colas concurrentes del sistema con diferentes prioridades (QoS).


Ejemplo: ejecutar una tarea en segundo plano y actualizar la UI



import UIKit

class ViewController: UIViewController { @IBOutlet weak var imageView: UIImageView!

func loadImage(from url: URL) { // Cambiamos a una cola en segundo plano DispatchQueue.global(qos: .background).async { [weak self] in guard let data = try? Data(contentsOf: url), let image = UIImage(data: data) else { return } // Volvemos al hilo principal para actualizar la UI DispatchQueue.main.async { self?.imageView.image = image } } }}


En este ejemplo, descargamos la imagen en un hilo en segundo plano para no bloquear la interfaz, y luego actualizamos la UI en el hilo principal.



DispatchGroup para sincronizar tareas



DispatchGroup permite rastrear la ejecución de un grupo de tareas asíncronas y ejecutar una acción después de que todas se completen.



let group = DispatchGroup()

group.enter()fetchData1 { result in print("Datos 1 recibidos") group.leave()}

group.enter()fetchData2 { result in print("Datos 2 recibidos") group.leave()}

group.notify(queue: .main) { print("Todos los datos cargados, actualizando la UI")}


2. OperationQueue — un enfoque orientado a objetos



OperationQueue es una abstracción de más alto nivel sobre GCD. Trabaja con objetos Operation, que representan una unidad de trabajo.



Ventajas de OperationQueue

  • Posibilidad de cancelar tareas (cancel).
  • Establecer dependencias entre operaciones (addDependency).
  • Monitorear el estado de la operación (isFinished, isExecuting, isCancelled).
  • Configurar el número máximo de operaciones paralelas.


Ejemplo: cargar múltiples imágenes



import UIKit

class ImageLoader { private let queue = OperationQueue() func loadImages(from urls: [URL], completion: @escaping ([UIImage]) -> Void) { var images: [UIImage] = [] let completionOperation = BlockOperation { DispatchQueue.main.async { completion(images) } } for url in urls { let o

Blogs

Book Recommendations