Files d'attente de tâches en Swift : de GCD à Swift Concurrency
Dans le développement iOS et macOS, la gestion de l'exécution parallèle du code est l'une des tâches clés. Les files d'attente de tâches (queues) permettent de répartir efficacement la charge entre les threads sans bloquer l'interface utilisateur. Dans ce guide, nous aborderons trois approches principales : le classique Grand Central Dispatch (GCD), l'abstraction OperationQueue et le mécanisme moderne Swift Concurrency (async/await).
1. Grand Central Dispatch (GCD) — le fondement du parallélisme
GCD est une bibliothèque C de bas niveau intégrée à Swift. Elle gère un pool de threads et propose deux types de files d'attente :
- Serial (séquentielles) — les tâches s'exécutent l'une après l'autre dans l'ordre d'ajout.
- Concurrent (parallèles) — les tâches démarrent simultanément, l'ordre d'achèvement n'est pas garanti.
Exemple de création et d'utilisation d'une file d'attente :
import Foundation
// Création d'une file d'attente séquentiellelet serialQueue = DispatchQueue(label: "com.example.serial")
serialQueue.async { print("Tâche 1 démarrée") sleep(1) print("Tâche 1 terminée")}
serialQueue.async { print("Tâche 2 démarrée") sleep(1) print("Tâche 2 terminée")}
// File d'attente parallèlelet concurrentQueue = DispatchQueue(label: "com.example.concurrent", attributes: .concurrent)
concurrentQueue.async { print("Tâche parallèle A")}
concurrentQueue.async { print("Tâche parallèle B")}Fonctionnalités clés de GCD :
DispatchQueue.main— la file d'attente principale (thread UI).DispatchQueue.global(qos: .userInitiated)— files d'attente globales avec priorité (QoS).dispatchGroup— synchronisation de plusieurs tâches.dispatchSemaphore— contrôle d'accès aux ressources.
2. OperationQueue — abstraction orientée objet
OperationQueue est construite au-dessus de GCD, mais offre une API de plus haut niveau. Principaux avantages :
- Gestion des dépendances entre opérations.
- Annulation de tâches (cancel).
- Surveillance de l'état (isFinished, isExecuting).
- Nombre maximum d'opérations parallèles.
Exemple avec BlockOperation :
import Foundation
let operationQueue = OperationQueue()operationQueue.maxConcurrentOperationCount = 2
let operation1 = BlockOperation { print("Opération 1 : chargement des données") sleep(2) print("Opération 1 terminée")}
let operation2 = BlockOperation { print("Opération 2 : traitement") sleep(1) print("Opération 2 terminée")}
// Définition d'une dépendance : l'opération 2 ne commencera qu'après la fin de l'opération 1operation2.addDependency(operation1)
operationQueue.addOperations([operation1, operation2], waitUntilFinished: false)
// Annulation d'une opérationoperation1.cancel()Quand utiliser OperationQueue :
- Chaînes de tâches complexes avec dépendances.
- Nécessité d'un contrôle fin (pause, annulation).
- Travail avec KVO (Key-Value Observing) pour la surveillance.
3. Swift Concurrency — l'approche moderne (iOS 13+, macOS 10.15+)
Depuis Swift 5.5, Apple a introduit un support intégré de la programmation asynchrone via async/await, Task et TaskGroup. C'est une manière plus sûre et plus lisible de travailler avec le parallélisme.
Exemple de base :
import Foundation
func fetchUserData() async -> String { // Simulation d'une requête réseau try? await Task.sleep(nanoseconds: 2 * 1_000_000_000) return "Données utilisateur chargées"}
func processData()