Programación asíncrona en Swift: guía completa 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

Introducción a la programación asíncrona en Swift

Las aplicaciones móviles y de escritorio modernas en Swift (iOS/macOS) requieren cada vez más la ejecución de operaciones largas —carga de datos desde la red, trabajo con archivos, procesamiento de imágenes— sin bloquear la interfaz de usuario. Hasta hace poco, los desarrolladores usaban closures (completion handlers) y Grand Central Dispatch (GCD), lo que llevaba al llamado «infierno de callbacks» y complicaba la lectura del código. Con el lanzamiento de Swift 5.5, Apple presentó un modelo fundamentalmente nuevo de programación asíncrona, basado en las palabras clave async y await, así como en actores y estructuras Task. En esta guía, analizaremos todos los conceptos clave con ejemplos prácticos.



1. Fundamentos de async/await en Swift

La palabra clave async indica que una función o método puede pausar su ejecución para esperar el resultado de una operación asíncrona. La llamada a dicha función se marca con la palabra await. Esto permite escribir código asíncrono de forma tan lineal como el código síncrono.



// Declaramos una función asíncronafunc fetchUserData(from url: URL) async throws -> Data {    let (data, _) = try await URLSession.shared.data(from: url)    return data}

// La usamos en el contexto de una tareaTask { do { let url = URL(string: "https://api.example.com/user")! let userData = try await fetchUserData(from: url) print("Datos recibidos: \\(userData.count) bytes") } catch { print("Error de carga: \\(error.localizedDescription)") }}


Nota: la llamada await pausa la tarea actual, pero no bloquea el hilo. El sistema cambia el contexto por sí mismo cuando el resultado está listo, lo que hace que el código sea eficiente y seguro.



2. Actores (Actors) — trabajo seguro con estado

La asincronía añade el problema de la condición de carrera (data race). Para solucionarlo, en Swift se introdujeron los actores. Un actor es un tipo de referencia que aísla su estado y garantiza que solo una tarea pueda acceder a sus propiedades mutables en cualquier momento.



actor Counter {    private var value = 0        func increment() {        value += 1    }        func getValue() -> Int {        return value    }}

// Uso del actorlet counter = Counter()

Task { await counter.increment() let currentValue = await counter.getValue() print("Valor actual: \\(currentValue)")}


La palabra clave actor hace que todos los métodos y propiedades (excepto los inmutables) sean asíncronos para el acceso externo. Esto permite evitar bloqueos y interbloqueos (deadlocks), típicos de la gestión manual de bloqueos (NSLock, DispatchSemaphore).



3. TaskGroup y ejecución paralela de tareas

Cuando es necesario ejecutar varias operaciones asíncronas independientes en paralelo, use TaskGroup. Es una estructura que permite lanzar tareas hijas y recopilar sus resultados.



func fetchMultipleUsers(ids: [Int]) async throws -> [User] {    try await withThrowingTaskGroup(of: User.self) { group in        var users: [User] = []                for id in ids {            group.addTask {                let url = URL(string: "https://api.example.com/users/\\(id)")!                let data = try await URLSession.shared.data(from: url)                return try JSONDecoder().decode(User.self, from: data.0)            }        }                for try await user in group {            users.append(user)        }        return users    }}

// UsoTask { let users = try? await fetchMultipleUsers(ids: [1, 2, 3, 4, 5]) print("Usuarios cargados: \\(users?.count ?? 0)")}


El método withThrowi

Blogs

Book Recommendations