Lorsque vous devez effectuer quelque chose sur le thread principal dans le bloc d'achèvement d'une tâche de mise en réseau ou d'une opération, laquelle de ces méthodes serait la plus appropriée et pourquoi?:
OperationQueue.main.addOperation
DispatchQueue.main.async
Pour plus de détails sur les différences entre les deux types de file d'attente, voir la réponse de Lion.
Les deux approches fonctionneront. Cependant, NSOperation
est surtout nécessaire lorsqu'une planification plus avancée (y compris dépendances, annulation, etc.) est requise. Donc, dans ce cas, un simple
DispatchQueue.main.async { /* do work */ }
sera très bien. Ce serait équivalent à
dispatch_async(dispatch_get_main_queue(), ^{ /* do work */ });
dans Objective-C, qui est aussi la façon dont je le ferais dans ce langage.
Quand utiliser NSOperation
L'API NSOperation
est idéale pour encapsuler des blocs de fonctionnalités bien définis. Vous pouvez, par exemple, utiliser une sous-classe NSOperation
pour encapsuler la séquence de connexion d'une application.
La gestion de la dépendance est la cerise sur le gâteau. Une opération peut avoir des dépendances avec d'autres opérations et c'est une fonctionnalité puissante qui manque à Grand Central Dispatch. Si vous devez effectuer plusieurs tâches dans un ordre spécifique, les opérations sont une bonne solution.
Vous pouvez aller trop loin avec les opérations si vous créez des dizaines d'opérations dans un court laps de temps. Cela peut entraîner des problèmes de performances en raison de la surcharge inhérente à NSOperation API
.
Quand utiliser Grand Central Dispatch
Grand Central Dispatch
est idéal si vous avez juste besoin d'envoyer un bloc de code dans une file d'attente série ou simultanée.
Si vous ne voulez pas passer par les tracas de la création d'un NSOperation subclass
pour une tâche banale, puis Grand Central Dispatch
est une excellente alternative. Un autre avantage de Grand Central Dispatch
est que vous pouvez conserver le code associé ensemble. Jetez un œil à l'exemple suivant.
let dataTask = session.dataTaskWithRequest(request, completionHandler: { (data, response, error) -> Void in
// Process Response
...
dispatch_async(dispatch_get_main_queue(), { () -> Void in
// Update User Interface
...
})
})
Dans le gestionnaire d'achèvement de la tâche de données, nous traitons la réponse et mettons à jour l'interface utilisateur en envoyant une fermeture (ou un bloc) à la file d'attente principale. Cela est nécessaire car nous ne savons pas sur quel thread le gestionnaire d'achèvement est exécuté et il s'agit très probablement d'un thread d'arrière-plan.
Cité textuellement par cette source
DispatchQueue gère l'exécution des éléments de travail. Chaque élément de travail soumis à une file d'attente est traité sur un pool de threads géré par le système.
Référence: Apple Doc
La classe NSOperationQueue régule l'exécution d'un ensemble d'objets Operation. Après avoir été ajoutée à une file d'attente, une opération reste dans cette file d'attente jusqu'à ce qu'elle soit explicitement annulée ou finisse d'exécuter sa tâche. Les opérations dans la file d'attente (mais pas encore en cours d'exécution) sont elles-mêmes organisées en fonction des niveaux de priorité et des dépendances des objets inter-opérations et sont exécutées en conséquence. Une application peut créer plusieurs files d'attente d'opérations et soumettre des opérations à l'une d'entre elles.
Référence: Apple Doc
Donc, vous devriez préférer DispatchQueue.main.async
lorsque vous souhaitez effectuer quelque chose sur le thread principal à partir du bloc d'achèvement d'un appel réseau. Surtout quand elle est liée à UI Updates
! Et si votre tâche est complexe, je veux dire que si vous avez besoin d'opérations supplémentaires sur la tâche en cours d'exécution, vous pouvez utiliser OperationQueue.main.addOperation
autrement DispatchQueue.main.async
donnera des performances plus optimales comparativement!