Travailler avec les files d'attente de tâches en Swift : de la théorie aux projets réels
\nDans le développement moderne pour iOS et macOS, la réactivité de l'interface est un facteur clé de succès d'une application. Chaque fois que vous effectuez une opération lourde (téléchargement d'image, analyse JSON, travail avec une base de données) sur le thread principal, l'utilisateur voit un "gel" de l'interface. La solution : les files d'attente de tâches. Dans cet article, nous allons analyser trois approches principales pour travailler avec les files d'attente en Swift : le GCD classique, l'OperationQueue de haut niveau et l'async/await moderne. Vous obtiendrez des exemples de code prêts à l'emploi et saurez quelle approche choisir pour une tâche spécifique.
\n\n1. Grand Central Dispatch (GCD) : démarrage rapide avec DispatchQueue
\nGrand Central Dispatch est une bibliothèque de bas niveau pour gérer l'exécution parallèle du code. Elle est à la base du multithreading en Swift et reste l'outil le plus performant pour les tâches d'arrière-plan simples.
\n\nTypes principaux de files d'attente :
\n- \n
main— file d'attente série du thread principal (toutes les mises à jour de l'interface utilisateur uniquement ici). \n global(qos:)— files d'attente parallèles avec priorités (userInteractive, userInitiated, utility, background). \n custom(label:)— votre propre file d'attente (peut être série ou parallèle). \n
Exemple : téléchargement d'image et mise à jour de l'interface utilisateur
\nimport UIKit\n\nclass ImageLoader {\n func loadImage(from url: URL, completion: @escaping (UIImage?) -> Void) {\n DispatchQueue.global(qos: .userInitiated).async {\n guard let data = try? Data(contentsOf: url),\n let image = UIImage(data: data) else {\n DispatchQueue.main.async {\n completion(nil)\n }\n return\n }\n DispatchQueue.main.async {\n completion(image)\n }\n }\n }\n}\n\nConseil pratique : Utilisez toujours .userInitiated pour les tâches que l'utilisateur attend immédiatement (par exemple, l'ouverture d'une image). Pour la synchronisation de données en arrière-plan, utilisez .background.
2. OperationQueue : gestion des dépendances et annulation des tâches
\nLorsque la logique devient plus complexe (besoin d'annuler une tâche, de définir un ordre d'exécution ou de limiter le nombre d'opérations parallèles), OperationQueue vient à la rescousse. Contrairement à GCD, les opérations sont des objets qui peuvent être réutilisés et contrôlés.
Fonctionnalités clés :
\n- \n
- Annulation des tâches via
cancel(). \n - Dépendances (
addDependency) — la tâche B ne s'exécutera qu'après la tâche A. \n - Contrôle du nombre maximum d'opérations parallèles (
maxConcurrentOperationCount). \n
Exemple : téléchargement de plusieurs images avec limitation du parallélisme
\nimport UIKit\n\nclass BatchImageDownloader {\n private let queue: OperationQueue = {\n let q = OperationQueue()\n q.maxConcurrentOperationCount = 3 // Pas plus de 3 téléchargements simultanés\n q.qualityOfService = .userInitiated\n return q\n }()\n \n func downloadImages(from urls: [URL], completion: @escaping ([UIImage]) -> Void) {\n var images: [UIImage] = []\n let syncQueue = DispatchQueue(label: "sync.images")\n \n let finishOperation = BlockOperation {\n DispatchQueue.main.async {\n completion(images)\n }\n }\n \n for url in urls {\n let operation = BlockOperation {\n guard let data = try? Data(contentsOf: url),\n let image = UIImage(data: data) else { return }\n syncQueue.async {\n images.append(image)\n }\n }\n