GCD vs async/await en Swift : guide technique complet

La gestion de la concurrence est un sujet central en développement iOS. Pendant des années, Grand Central Dispatch (GCD) a été la solution principale pour exécuter du code en arrière-plan.

Depuis Swift 5.5, Apple a introduit async/await et la concurrence structurée, une approche plus moderne, plus sûre et plus lisible.

Cet article compare en profondeur GCD et async/await :

  • leurs modèles mentaux,
  • leurs différences techniques,
  • leurs forces et faiblesses,
  • et quand utiliser l’un ou l’autre en production.

1. Grand Central Dispatch (GCD) : principes fondamentaux

GCD est une API bas niveau introduite par Apple pour gérer la concurrence via des queues de tâches.

L’idée clé :

Tu décris où le code doit s’exécuter (quelle queue), pas quand ni sur quel thread exact.

1.1 Queues de dispatch

GCD fournit plusieurs types de queues :

  • Main queue : liée au thread principal (UI).
  • Global queues : queues concurrentes avec différentes priorités.
  • Custom queues : sérialisées ou concurrentes.

DispatchQueue.global(qos: .background).async {
    // Travail en arrière-plan
    DispatchQueue.main.async {
        // Mise à jour UI
    }
}

1.2 Avantages de GCD

  • Très performant.
  • Contrôle précis des queues.
  • Compatible avec toutes les versions iOS modernes.

1.3 Limites de GCD

  • Code difficile à lire (pyramide de closures).
  • Pas de structure explicite des tâches.
  • Gestion manuelle des erreurs.
  • Annulation complexe.

2. async/await : la concurrence structurée

async/await introduit un modèle de concurrence de haut niveau, centré sur la lisibilité et la sécurité.

L’objectif :

Écrire du code asynchrone qui ressemble à du code synchrone.

2.1 Exemple simple


func loadUser() async throws -> User {
    let data = try await api.fetchUser()
    return data
}

Le mot-clé await suspend la fonction sans bloquer le thread.

2.2 Avantages d’async/await

  • Code linéaire et lisible.
  • Gestion native des erreurs (throws).
  • Annulation intégrée.
  • Moins de bugs de concurrence.

2.3 Limites d’async/await

  • Nécessite iOS 13+ (et iOS 15+ pour certaines APIs).
  • Moins de contrôle bas niveau.
  • Interopérabilité parfois nécessaire avec GCD ou Combine.

3. Différences fondamentales de modèle

3.1 GCD : concurrence non structurée

Avec GCD, chaque bloc est indépendant. Le développeur doit gérer :

  • la synchronisation,
  • les dépendances,
  • la durée de vie des tâches.

3.2 async/await : concurrence structurée

Les tâches sont hiérarchiques :

  • une tâche parente attend ses enfants,
  • les erreurs et l’annulation se propagent.

async let user = fetchUser()
async let posts = fetchPosts()

let result = try await (user, posts)

4. Gestion des erreurs

4.1 Avec GCD

Les erreurs sont généralement gérées via des closures :


loadData { result in
    switch result {
    case .success(let data):
        print(data)
    case .failure(let error):
        print(error)
    }
}

4.2 Avec async/await

Les erreurs utilisent le système natif de Swift :


do {
    let data = try await loadData()
} catch {
    print(error)
}

5. Annulation

5.1 GCD

GCD ne fournit pas de mécanisme d’annulation automatique. Il faut implémenter des flags manuellement.

5.2 async/await

L’annulation est intégrée :


try Task.checkCancellation()

Une tâche annulée propage automatiquement l’annulation.


6. Performance et threads

Les deux solutions utilisent le même pool de threads système.

  • async/await n’est pas plus lent que GCD.
  • Il réduit surtout les erreurs humaines.
  • Les suspensions ne bloquent pas les threads.

7. Interopérabilité GCD ? async/await

Il est courant de combiner les deux :

7.1 Appeler du GCD depuis async


await withCheckedContinuation { continuation in
    DispatchQueue.global().async {
        continuation.resume(returning: "Done")
    }
}

7.2 Appeler async depuis GCD


DispatchQueue.global().async {
    Task {
        await loadData()
    }
}

8. Quand utiliser GCD aujourd’hui ?

  • Interopérabilité avec du code legacy.
  • Traitements très bas niveau.
  • Support de versions iOS anciennes.

9. Quand utiliser async/await ?

  • Nouvelles applications.
  • Logique métier asynchrone.
  • Code testable et maintenable.
  • SwiftUI et architectures modernes.

Conclusion

GCD et async/await reposent sur les mêmes fondations système, mais proposent des modèles mentaux très différents.

  • GCD : puissant mais verbeux et risqué.
  • async/await : lisible, structuré, sûr.

En 2025, async/await est la solution recommandée par Apple pour la majorité des cas, tandis que GCD reste un outil de support pour le code existant et les cas bas niveau.