iOS Les methods sont-elles appelées par les delegates et les observateurs exécutés sur le thread principal?

Désolé, je ne suis pas sûr de la bonne langue ici, mais quand les methods sont appelées parce qu'elles sont soit des methods déléguées, soit des methods appelées comme étant la cible d'un observateur, sont-elles exécutées sur le thread principal?

Je me request si je peux juste faire des changements d'interface user dans ces methods, ou dois-je les envelopper dans

dispatch_async(dispatch_get_main_queue(), ^{ UI stuff }); 

TIA: John

Pour les delegates cela peut varier. Si la documentation ne spécifie pas, ils sont généralement envoyés sur le thread principal. Traditionnellement UIKit doit être utilisé sur le thread principal afin que ces delegates seront presque toujours appelés à partir du fil principal.

Pour les notifications je pense que vous voulez ce petit snip.

Un centre de notification envoie des notifications aux observateurs de manière synchrone. En d'autres termes, les methods postNotification: ne returnnent pas tant que tous les observateurs n'ont pas reçu et traité la notification. Pour envoyer des notifications de manière asynchronous, utilisez NSNotificationQueue. Dans une application multithread, les notifications sont toujours envoyées dans le thread dans lequel la notification a été publiée, ce qui peut ne pas être le même thread dans lequel un observateur s'est enregistré .

De http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/nsnotificationcenter_Class/Reference/Reference.html

Et enfin pour KVO, les notifications peuvent provenir d'autres threads. Voici ce qu'un ingénieur d'Apple avait à dire à propos de leur manipulation.

http://lists.apple.com/archives/cocoa-dev/2007/May/msg00022.html

Comme indiqué, le fil varie en fonction de l'appelant. Dans votre méthode de délégué, si vous avez besoin de vous adapter, vous pouvez toujours faire quelque chose comme ceci:

 if ([NSThread isMainThread]) { // do the UI stuff as normal } else { dispatch_async(dispatch_get_main_queue(), ^{ UI stuff }); } 

L'idée de base est que dans tous les cas, la méthode d'observateur ou de délégué est appelée dans le même thread que la notification initiale (pour le model d'observateur) ou le code de délégation sont en cours d'exécution, donc si vous n'êtes pas sûr fil principal. Je vais essayer de justifier ces déclarations dans le raisonnement ci-dessous, bien sûr que je peux me tromper.

Sauf indication contraire dans la documentation du protocole délégué, dans le model délégué, une méthode est appelée directement dans le même thread que l'appelant est en cours d'exécution au moment de l'appel. Par exemple, si l'appelant (object délégué) veut appeler son délégué et qu'il s'exécute actuellement sur "Thread-1", l'appel se produira dans le même thread:

 // this is running in "Thread-1" --> then aDelegateMethod will continue on "Thread-1" [myDelegate aDelegateMethod] 

En ce qui concerne le model d'observateur, je ne vois aucune raison valable pour que le système envoie explicitement une notification d'observation sur le thread principal, en particulier si la modification de la valeur d'origine qui triggers la notification est en cours dans un autre thread. En fait, dans le cas de KVO, le moteur d'exécution modifie la définition de class en ajoutant des methods privées qui surchargent les methods setter pour faire les notifications, et je ne vois pas de raison valable de faire cet appel explicitement dans le thread principal. Donc, selon moi, une notification KVO peut provenir de n'importe quel thread et ce thread est le même que celui qui exécute le changement de valeur dans la class observée.

Enfin, le mécanisme basé sur NSNotificationCenter voit ses notifications appelées par le même thread où la notification d'origine a été publiée. Ceci est clairement indiqué dans la documentation d'Apple (et cela vaut la peine de dire que chaque thread a sa propre queue de notification).

Donc, dans tous les cas, le thread est maintenu et si vous voulez être sûr que votre bloc d'interface user est appelé dans la queue principale, utilisez l'appel GCD que vous avez posté dans votre question.