Quelqu'un peut-il expliquer ce que c'est NSRunLoop
? comme je le sais, NSRunLoop
est-ce que quelque chose est lié à NSThread
non? Supposons donc que je crée un fil comme
NSThread* th=[[NSThread alloc] initWithTarget:self selector:@selector(someMethod) object:nil];
[th start];
-(void) someMethod
{
NSLog(@"operation");
}
donc après que ce fil ait terminé son travail, non? pourquoi utiliser RunLoops
ou où utiliser? à partir de la documentation Apple, j'ai lu quelque chose mais ce n'est pas clair pour moi, alors veuillez expliquer aussi simple que possible
ios
objective-c
cocoa-touch
nsrunloop
taffarel
la source
la source
Réponses:
Une boucle d'exécution est une abstraction qui (entre autres) fournit un mécanisme pour gérer les sources d'entrée du système (sockets, ports, fichiers, clavier, souris, minuteries, etc.).
Chaque NSThread a sa propre boucle d'exécution, accessible via la méthode currentRunLoop.
En général, vous n'avez pas besoin d'accéder directement à la boucle d'exécution, bien que certains composants (réseau) vous permettent de spécifier la boucle d'exécution qu'ils utiliseront pour le traitement d'E / S.
Une boucle d'exécution pour un thread donné attendra qu'une ou plusieurs de ses sources d'entrée aient des données ou un événement, puis déclenchera le ou les gestionnaires d'entrée appropriés pour traiter chaque source d'entrée qui est "prête".
Après cela, il retournera à sa boucle, traitant les entrées provenant de diverses sources, et «dormant» s'il n'y a pas de travail à faire.
C'est une description de niveau assez élevé (en essayant d'éviter trop de détails).
ÉDITER
Une tentative pour répondre au commentaire. Je l'ai cassé en morceaux.
En effet. NSRunLoop n'est pas thread-safe et ne doit être accessible qu'à partir du contexte du thread qui exécute la boucle.
Si vous souhaitez surveiller un port, vous ajouterez simplement ce port à la boucle d'exécution, puis la boucle d'exécution surveillera l'activité de ce port.
Vous pouvez également ajouter une minuterie explicitement avec
La boucle d'exécution traitera tous les événements prêts à chaque itération (selon son mode). Vous devrez consulter la documentation pour découvrir les modes d'exécution, car cela dépasse un peu le cadre d'une réponse générale.
Dans la plupart des applications, la boucle d'exécution principale s'exécutera automatiquement. Cependant, vous êtes responsable du démarrage de la boucle d'exécution et de la réponse aux événements entrants pour les threads que vous faites tourner.
Je ne sais pas ce que vous voulez dire ici. Vous n'ajoutez pas d'événements à la boucle d'exécution. Vous ajoutez des sources d'entrée et des sources de minuterie (à partir du thread qui possède la boucle d'exécution). La boucle de course les surveille ensuite pour l'activité. Vous pouvez, bien sûr, fournir des données d'entrée à partir d'autres threads et processus, mais l'entrée sera traitée par la boucle d'exécution qui surveille ces sources sur le thread qui exécute la boucle d'exécution.
En effet. En fait, une boucle d'exécution "restera" dans un gestionnaire d'événements jusqu'à ce que ce gestionnaire d'événements soit retourné. Vous pouvez le voir dans n'importe quelle application assez simplement. Installez un gestionnaire pour toute action d'E / S (par exemple, appuyez sur un bouton) qui se met en veille. Vous bloquerez la boucle d'exécution principale (et toute l'interface utilisateur) jusqu'à ce que cette méthode se termine.
La même chose s'applique à toute boucle d'exécution.
Je vous suggère de lire la documentation suivante sur les boucles d'exécution:
https://developer.apple.com/documentation/foundation/nsrunloop
et comment ils sont utilisés dans les threads:
https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/Multithreading/RunLoopManagement/RunLoopManagement.html#//apple_ref/doc/uid/10000057i-CH16-SW1
la source
performSelector:onThread:withObject:waitUntilDone:
, en passant unNSThread
objet et votre sélecteur sera planifié sur la boucle d'exécution de ce thread.Ils vous permettent d'attendre que l'utilisateur tape et de répondre en conséquence, d'attendre que vous obteniez un completionHandler et d'appliquer ses résultats, d'attendre d'avoir une minuterie et d'exécuter une fonction. Si vous n'avez pas de boucle d'exécution, vous ne pouvez pas écouter / attendre les tapotements des utilisateurs, vous ne pouvez pas attendre qu'un appel réseau se produise, vous ne pouvez pas être réveillé en x minutes à moins d'utiliser
DispatchSourceTimer
ouDispatchWorkItem
Également de ce commentaire :
Plus précisément à propos de: "Les threads d'arrière-plan n'ont pas leurs propres boucles d'exécution". Le minuteur suivant ne parvient pas à se déclencher pour une distribution asynchrone :
Je pense que la raison pour laquelle le
sync
bloc fonctionne également est que:Les blocs de synchronisation ne sont généralement exécutés qu'à partir de leur file d'attente source . Dans cet exemple, la file d'attente source est la file d'attente principale, la file d'attente quelle qu'elle soit est la file d'attente de destination.
Pour tester cela, je me suis connecté
RunLoop.current
à chaque envoi.La distribution de synchronisation avait la même boucle d'exécution que la file d'attente principale. Alors que le RunLoop dans le bloc async était une instance différente des autres. Vous vous demandez peut-être pourquoi
RunLoop.current
renvoie une valeur différente. N'est-ce pas une valeur partagée !? Excellente question! Lire la suite:NOTE IMPORTANTE:
La propriété de classe
current
n'est PAS une variable globale.C'est contextuel. Il n'est visible que dans la portée du thread, c'est -à- dire le stockage local du thread . Pour en savoir plus, cliquez ici .
Il s'agit d'un problème connu avec les minuteries. Vous n'avez pas le même problème si vous utilisez
DispatchSourceTimer
la source
Les RunLoops sont un peu comme une boîte où les choses se passent simplement.
Fondamentalement, dans un RunLoop, vous allez traiter certains événements puis revenir. Ou retournez s'il ne traite aucun événement avant que le délai d'attente ne soit atteint. Vous pouvez le dire comme similaire aux NSURLConnections asynchrones, traiter les données en arrière-plan sans interférer avec votre boucle actuelle et, en même temps, vous avez besoin de données de manière synchrone. Ce qui peut être fait avec l'aide de RunLoop qui rend votre asynchrone
NSURLConnection
et fournit des données au moment de l'appel. Vous pouvez utiliser un RunLoop comme ceci:Dans ce RunLoop, il fonctionnera jusqu'à ce que vous ayez terminé certains de vos autres travaux et que vous définissiez YourBoolFlag sur false .
De même, vous pouvez les utiliser dans les threads.
J'espère que cela vous aide.
la source
D'ici
D'ici
la source