OperationQueue — qu'est-ce que c'est, Operation et gestion des tâches

Auteur : IT Sectr Publié le : 2026-03-16 Temps de lecture : 8 min

OperationQueue est une file d'attente de tâches de haut niveau dans iOS et macOS construite au-dessus de Grand Central Dispatch. Selon Apple Developer Documentation, 2026, OperationQueue gère des instances d'Operation — des objets qui encapsulent une unité de travail. Contrairement à DispatchQueue, OperationQueue prend en charge les dépendances entre les opérations, les priorités, l'observation KVO et l'annulation des tâches en cours d'exécution. OperationQueue gère automatiquement un pool de threads, répartissant les opérations sur les ressources système disponibles.

Points Clés

  • OperationQueue — une file d'attente de haut niveau avec prise en charge des dépendances entre opérations
  • Operation — une classe abstraite pour encapsuler une unité de travail avec état
  • BlockOperation — une implémentation simplifiée d'Operation pour un seul bloc de code
  • Les dépendances définissent l'ordre d'exécution : l'opération B s'exécute après A
  • L'annulation des opérations est prise en charge via la propriété isCancelled compatible KVO

Qu'est-ce que OperationQueue et Operation

OperationQueue est une classe du framework Foundation qui gère l'exécution des objets Operation. Contrairement à DispatchQueue, OperationQueue ne nécessite pas de spécifier explicitement le mode série ou concurrent — le nombre d'opérations exécutées simultanément est contrôlé par la propriété maxConcurrentOperationCount. La valeur 1 rend la file d'attente séquentielle, toute autre valeur la rend concurrente.

Operation est une classe abstraite représentant une unité de travail. Chaque opération a un état : ready, executing, finished ou cancelled. Les états sont compatibles avec KVO (Key-Value Observing), ce qui permet de réagir aux changements — par exemple, mettre à jour l'interface lorsqu'une opération se termine. Operation gère automatiquement les indicateurs isExecuting et isFinished.

Selon Apple (2026), OperationQueue utilise GCD en interne mais ajoute des fonctionnalités non disponibles dans DispatchQueue : dépendances, priorités et annulation des opérations. Si l'application passe en arrière-plan, OperationQueue suspend l'exécution et la reprend au retour. OperationQueue prend également en compte automatiquement le nombre de cœurs CPU et sélectionne le nombre optimal de threads.

Cycle de Vie d'une Operation

Chaque opération passe par quatre états : pending (en attente), ready (prête), executing (en cours d'exécution) et finished (terminée). L'état cancelled peut survenir à n'importe quelle étape avant la fin. Les transitions d'état sont suivies via KVO — c'est la base des mises à jour réactives de l'interface. OperationQueue supprime automatiquement les opérations terminées de la file et notifie les opérations dépendantes que leur prérequis est rempli, déclenchant leur exécution.

Operation et BlockOperation : Implémentation des Tâches

Operation est une classe abstraite qui nécessite de redéfinir la méthode main() ou start(). Le code de la tâche est placé dans la méthode main(), et les états isExecuting et isFinished sont gérés automatiquement. Pour les opérations asynchrones, il est nécessaire de redéfinir start() et de gérer manuellement les indicateurs d'état.

BlockOperation est une implémentation concrète d'Operation qui exécute un ou plusieurs blocs de code. BlockOperation devient concurrent si vous ajoutez plusieurs blocs via addExecutionBlock(). L'opération se termine uniquement après l'exécution de tous les blocs ajoutés. BlockOperation est une alternative pratique pour les tâches simples sans héritage.

CaractéristiqueOperationBlockOperation
Type de ClasseAbstraiteConcrète
HéritageRequisNon requis
AsynchronieGestion manuelle KVOAutomatique
Blocs de CodeUn dans main()Un ou plusieurs
UtilisationTâches complexes avec étatTâches simples uniques
Adapté pourDépendances, annulation, progressionBlocs rapides, achèvement
MémoirePlus élevée à cause de KVO et de l'étatMinimale, légère

Création d'une Operation Personnalisée

Pour créer une opération personnalisée, héritez de Operation et redéfinissez main(). À l'intérieur, vérifiez l'indicateur isCancelled avant les opérations coûteuses pour garantir une annulation rapide. Ceci est critique pour le téléchargement de fichiers volumineux ou le traitement par lots de données. Le choix entre Operation et BlockOperation dépend de la complexité de la tâche : pour les actions simples uniques, BlockOperation suffit ; pour une logique réutilisable avec état, héritez de Operation.

Dépendances et Priorités des Opérations

Les dépendances sont l'avantage clé d'OperationQueue par rapport à DispatchQueue. La méthode addDependency(_:) spécifie que l'opération B s'exécute uniquement après la fin de l'opération A. Les dépendances forment un graphe orienté acyclique (DAG) : si une dépendance cyclique est ajoutée, la file d'attente l'ignore et les opérations ne démarrent pas.

La priorité d'une opération est définie via la propriété queuePriority avec les valeurs : .veryLow, .low, .normal, .high, .veryHigh. La priorité affecte l'ordre de démarrage parmi les opérations prêtes mais n'annule pas les dépendances. OperationQueue résout d'abord les dépendances, puis applique la priorité parmi les opérations disponibles.

Exemple Pratique de Dépendances

Un scénario typique — le chargement des données de profil : d'abord charger l'utilisateur, puis en fonction de son id charger les amis et les publications. Définir une dépendance entre charger l'utilisateur et charger les amis garantit l'ordre correct sans gestionnaires d'achèvement imbriqués.

Limitation de la Concurrence

La propriété maxConcurrentOperationCount limite le nombre d'opérations exécutées simultanément. La valeur 1 crée une file d'attente séquentielle, la valeur par défaut (NSOperationQueueDefaultMaxConcurrentOperationCount) est optimale pour le système et dépend de la charge actuelle de l'appareil. La configuration appropriée de ce paramètre empêche une consommation excessive de ressources : pour le chargement d'images, 4 à 6 opérations concurrentes suffisent ; pour les tâches intensives en CPU, utilisez le nombre de cœurs du processeur.

OperationQueue vs DispatchQueue : Comparaison

Le choix entre OperationQueue et DispatchQueue dépend de la complexité de la tâche. DispatchQueue est un outil léger pour les appels asynchrones simples. OperationQueue est une solution plus lourde pour les scénarios complexes avec de nombreuses tâches interdépendantes. Apple recommande de commencer avec DispatchQueue et de passer à OperationQueue uniquement lorsque des dépendances ou une annulation sont nécessaires. Pour la plupart des projets iOS, une combinaison des deux outils offre un équilibre optimal entre performances et flexibilité.

  • DispatchQueue — léger, rapide, sans surcharge des objets Operation
  • OperationQueue — prend en charge les dépendances, l'annulation, KVO et les priorités
  • DispatchQueue — idéal pour les tâches async/asyncAfter simples et la synchronisation série
  • OperationQueue — indispensable pour les algorithmes pas à pas avec des étapes séquentielles
  • DispatchQueue — s'intègre avec Swift Concurrency (async/await) via Continuation

Selon Ray Wenderlich (2025), dans les grands projets iOS, OperationQueue est utilisé pour charger du contenu avec progression et annulation, tandis que DispatchQueue est utilisé pour toutes les autres opérations asynchrones. Le ratio est d'environ 20 pour 80 en faveur de DispatchQueue.

Exemples de Code avec OperationQueue en Swift

Examinons trois exemples : un BlockOperation simple, une Operation personnalisée avec dépendances et une opération annulable pour le chargement de données.

BlockOperation avec Achèvement

Le cas le plus simple — exécuter un bloc sur OperationQueue et traiter le résultat via completionBlock. Chaque Operation a une propriété completionBlock intégrée, appelée après la fin de main().

swift
let queue = OperationQueue()
let operation = BlockOperation()
operation.addExecutionBlock {
    let data = NetworkService.fetchData()
    OperationQueue.main.addOperation {
        self.updateUI(data)
    }
}
queue.addOperation(operation)

Dépendances Entre Opérations

La dépendance garantit que parseOperation ne démarre qu'après la fin de downloadOperation. Cela élimine le besoin de callbacks imbriqués.

swift
let download = BlockOperation { self.downloadJSON() }
let parse = BlockOperation { self.parseJSON() }
parse.addDependency(download)

let queue = OperationQueue()
queue.addOperations([download, parse], waitUntilFinished: false)

Opération Personnalisée Annulable

Redéfinissez main() avec des vérifications périodiques de isCancelled. Cela permet à l'opération de s'arrêter immédiatement lors de l'annulation, sans attendre la fin d'une opération coûteuse.

swift
class ImageLoadOperation: Operation {
    override func main() {
        guard !self.isCancelled else { return }
        let image = self.downloadImage()
        guard !self.isCancelled else { return }
        OperationQueue.main.addOperation { self.display(image) }
    }
}

Annulation des Opérations et Observation KVO

L'annulation d'une opération définit l'indicateur isCancelled sur true, mais n'arrête pas la méthode main() déjà en cours d'exécution. Le code à l'intérieur de main() doit vérifier isCancelled par lui-même et se terminer si nécessaire. C'est une décision architecturale d'Apple — permettant au développeur de libérer correctement les ressources lors de l'annulation.

L'observation KVO des propriétés isFinished et isExecuting permet de réagir à l'achèvement des opérations sans callbacks explicites. OperationQueue supprime automatiquement les opérations terminées de la file, mais elles restent en mémoire tant qu'il y a des références fortes vers elles. KVO est la base pour intégrer OperationQueue avec des frameworks réactifs comme RxSwift ou Combine.

Gestion de l'Annulation via KVO

S'abonner à isCancelled via KVO permet de mettre à jour l'interface lors de l'annulation d'une opération — par exemple, afficher un espace réservé au lieu d'un téléchargement annulé. La propriété isCancelled est compatible KVO, ce qui la rend pratique pour les pipelines réactifs.

Meilleures Pratiques pour Travailler avec OperationQueue

Ne créez pas de grandes quantités d'opérations — chaque Operation est un objet séparé en mémoire. Si une tâche est courte et ne nécessite pas de dépendances, utilisez DispatchQueue directement. OperationQueue est justifiée pour les scénarios complexes avec des dépendances explicites, une annulation et un suivi de progression.

Vérifiez isCancelled avant les opérations coûteuses à l'intérieur de la méthode main(). Dans les cas de téléchargement de fichiers ou de traitement d'images, vérifier après chaque étape importante garantit une réponse rapide à l'annulation. Utilisez if isCancelled { return } au début de main() et après chaque opération majeure.

Gérez completionBlock correctement. La propriété completionBlock d'une opération est appelée après la fin de main(), même si l'opération a été annulée. Vérifiez isCancelled à l'intérieur de completionBlock pour éviter de mettre à jour l'interface avec des données erronées. OperationQueue.main est une file d'attente thread-safe pour les opérations d'interface, similaire à DispatchQueue.main.

Évitez les dépendances cycliques — elles empêchent toute opération dans le cycle de démarrer. OperationQueue ne détecte pas automatiquement les cycles : si A dépend de B et B dépend de A, les deux resteront dans l'état ready pour toujours. Planifiez le graphe de dépendances à l'avance.

Foire Aux Questions

En quoi OperationQueue diffère-t-il de DispatchQueue ?

OperationQueue est construit sur GCD et ajoute des dépendances, des priorités, KVO et l'annulation d'opérations. DispatchQueue est un outil plus léger pour les tâches asynchrones simples sans ces capacités.

Comment rendre la file d'attente séquentielle ?

Définissez la propriété maxConcurrentOperationCount sur 1. Cela transforme OperationQueue en une file d'attente séquentielle tout en conservant tous les avantages — dépendances, priorités et annulation.

Peut-on annuler une opération en cours d'exécution ?

La méthode cancel() définit l'indicateur isCancelled mais n'arrête pas la méthode main() en cours d'exécution. Le code de l'opération doit vérifier isCancelled par lui-même et se terminer. L'annulation fonctionne uniquement pour les opérations en attente et prêtes.

Quand dois-je utiliser Operation au lieu de BlockOperation ?

Vous devez hériter de Operation lorsque vous avez besoin de gestion d'état, d'asynchronie ou de réutilisation de logique. BlockOperation convient aux tâches simples uniques sans héritage.

OperationQueue bloque-t-il le thread principal ?

Non, sauf si vous appelez waitUntilFinished avec le paramètre true sur le thread principal. Les opérations s'exécutent sur des threads d'arrière-plan par défaut, et les résultats sont renvoyés via OperationQueue.main.

Résumé

  • OperationQueue — une file d'attente de haut niveau avec dépendances, priorités et annulation d'opérations
  • Operation — une classe abstraite pour encapsuler le travail avec un état compatible KVO
  • BlockOperation — une implémentation simplifiée pour un ou plusieurs blocs de code
  • Les dépendances définissent l'ordre d'exécution entre les opérations via un graphe sans cycles
  • L'annulation nécessite une vérification manuelle de isCancelled dans la méthode main() de l'opération
  • maxConcurrentOperationCount = 1 transforme la file en mode séquentiel
  • OperationQueue vs DispatchQueue — choisissez OperationQueue uniquement lorsque des dépendances ou KVO sont nécessaires

Nous développerons une application mobile clé en main

IT Sectr crée des applications iOS et Android pour les startups et les entreprises depuis 2017. Nous vous conseillerons et vous proposerons la meilleure solution.

Discuter du projet

Lisez aussi