J'ai une méthode qui accepte un bloc et un bloc de complétion. Le premier bloc doit s'exécuter en arrière-plan, tandis que le bloc d'achèvement doit s'exécuter dans la file d'attente où la méthode a été appelée.
Pour ce dernier, j'ai toujours utilisé dispatch_get_current_queue()
, mais il semble qu'il soit obsolète dans iOS 6 ou supérieur. Que dois-je utiliser à la place?
dispatch_get_current_queue()
est obsolète dans iOS 6? la documentation n'en dit rienRéponses:
Le modèle de "courir sur n'importe quelle file d'attente de l'appelant" est attrayant, mais finalement pas une bonne idée. Cette file d'attente peut être une file d'attente de faible priorité, la file d'attente principale ou une autre file d'attente avec des propriétés étranges.
Mon approche préférée à ce sujet est de dire "le bloc de complétion s'exécute sur une file d'attente définie par l'implémentation avec ces propriétés: x, y, z", et de laisser le bloc se répartir vers une file d'attente particulière si l'appelant veut plus de contrôle que cela. Un ensemble typique de propriétés à spécifier serait quelque chose comme "série, non réentrant et asynchrone par rapport à toute autre file d'attente visible par l'application".
** ÉDITER **
Catfish_Man a mis un exemple dans les commentaires ci-dessous, je l'ajoute simplement à sa réponse.
la source
C'est fondamentalement la mauvaise approche pour l'API que vous décrivez. Si une API accepte un bloc et un bloc d'achèvement à exécuter, les faits suivants doivent être vrais:
Le "blocage à exécuter" doit être exécuté sur une file d'attente interne, par exemple une file d'attente privée pour l'API et donc entièrement sous le contrôle de cette API. La seule exception à cela est si l'API déclare spécifiquement que le bloc sera exécuté sur la file d'attente principale ou sur l'une des files d'attente simultanées globales.
Le bloc d'achèvement doit toujours être exprimé comme un tuple (file d'attente, bloc) à moins que les mêmes hypothèses que pour # 1 ne soient vraies, par exemple le bloc d'achèvement sera exécuté sur une file d'attente globale connue. Le bloc d'achèvement doit en outre être distribué de manière asynchrone sur la file d'attente transmise.
Ce ne sont pas seulement des points stylistiques, ils sont entièrement nécessaires si votre API doit être à l'abri des blocages ou de tout autre comportement de cas de bord qui vous accrocherait un jour à l'arbre le plus proche. :-)
la source
Les autres réponses sont excellentes, mais pour moi, la réponse est structurelle. J'ai une méthode comme celle-ci sur un Singleton:
qui a deux dépendances, qui sont:
et
De cette façon, je centralise mes appels pour les répartir sur l'autre thread.
la source
Vous devez
dispatch_get_current_queue
en premier lieu faire attention à votre utilisation . Depuis le fichier d'en-tête:Vous pouvez faire l'une des deux choses suivantes:
Conservez une référence à la file d'attente sur laquelle vous avez initialement publié (si vous l'avez créée via
dispatch_queue_create
) et utilisez-la à partir de là.Utilisez les files d'attente définies par le système via
dispatch_get_global_queue
et gardez une trace de celle que vous utilisez.En effet, tout en comptant auparavant sur le système pour suivre la file d'attente dans laquelle vous vous trouvez, vous devrez le faire vous-même.
la source
dispatch_get_current_queue()
pour savoir de quelle file d'attente il s'agit? Parfois, le code qui a besoin de savoir sur quelle file d'attente il s'exécute n'a aucun contrôle ou aucune connaissance de celui-ci. J'ai beaucoup de code qui peut (et devrait) être exécuté sur une file d'attente en arrière-plan, mais j'ai parfois besoin de mettre à jour l'interface graphique (barre de progression, etc.), et j'ai donc besoin de dispatch_sync () vers la file d'attente principale pour ces opérations. Si déjà dans la file d'attente principale, dispatch_sync () se verrouille pour toujours. Cela me prendra des mois pour refactoriser mon code pour cela.Apple était obsolète
dispatch_get_current_queue()
, mais a laissé un trou à un autre endroit, nous sommes donc toujours en mesure d'obtenir la file d'attente de distribution actuelle:Cela fonctionne au moins pour la file d'attente principale. Notez que cette
underlyingQueue
propriété est disponible depuis iOS 8.Si vous devez effectuer le bloc de complétion dans la file d'attente d'origine, vous pouvez également utiliser
OperationQueue
directement, je veux dire sans GCD.la source
Pour ceux qui ont encore besoin de comparer les files d'attente, vous pouvez comparer les files d'attente par leur étiquette ou leur spécification. Vérifiez ceci https://stackoverflow.com/a/23220741/1531141
la source
C'est une réponse moi aussi. Je vais donc parler de notre cas d'utilisation.
Nous avons une couche de services et la couche d'interface utilisateur (entre autres couches). La couche de services exécute les tâches en arrière-plan. (Tâches de manipulation de données, tâches CoreData, appels réseau, etc.). La couche de service a quelques files d'attente d'opérations pour satisfaire les besoins de la couche d'interface utilisateur.
La couche d'interface utilisateur s'appuie sur la couche de services pour effectuer son travail, puis exécuter un bloc de réussite. Ce bloc peut contenir du code UIKit. Un cas d'utilisation simple consiste à récupérer tous les messages du serveur et à recharger la vue de collection.
Ici, nous garantissons que les blocs passés dans la couche services sont distribués dans la file d'attente sur laquelle le service a été appelé. Puisque dispatch_get_current_queue est une méthode obsolète, nous utilisons NSOperationQueue.currentQueue pour obtenir la file d'attente actuelle de l'appelant. Note importante sur cette propriété.
Puisque nous invoquons toujours nos services sur une file d'attente connue (nos files d'attente personnalisées et la file d'attente principale), cela fonctionne bien pour nous. Nous avons des cas où serviceA peut appeler serviceB qui peut appeler serviceC. Puisque nous contrôlons la provenance du premier appel de service, nous savons que le reste des services suivra les mêmes règles.
Ainsi, NSOperationQueue.currentQueue retournera toujours l'une de nos files d'attente ou la MainQueue.
la source