web-dev-qa-db-fra.com

NSDefaultRunLoopMode vs NSRunLoopCommonModes

Chers braves gens de stackoverflow,

Tout comme la dernière fois, je soulève une question sur laquelle je suis récemment tombé. J'espère que quelqu'un pourrait m'éclairer.

Chaque fois que j'essaie de télécharger un gros fichier derrière UIScrollView, MPMapView ou quelque chose, le processus de téléchargement s'arrête dès que je touche l'écran de l'iPhone. Heureusement, un article de blog génial de Jörn suggère une option alternative, en utilisant NSRunLoopCommonModes pour la connexion.

Cela me fait regarder en détail les deux modes, NSDefaultRunLoopMode et NSRunLoopCommonModes, mais le document Apple Apple n'explique pas gentiment, à part dire

NSDefaultRunLoopMode

Mode de gestion des sources d'entrée autres que les objets NSConnection. Il s'agit du mode de boucle d'exécution le plus couramment utilisé.

NSRunLoopCommonModes

Les objets ajoutés à une boucle d'exécution utilisant cette valeur comme mode sont surveillés par tous les modes de boucle d'exécution qui ont été déclarés comme membre de l'ensemble des modes "communs"; voir la description de CFRunLoopAddCommonMode pour plus de détails.

CFRunLoopAddCommonMode

Les sources, les temporisateurs et les observateurs sont enregistrés dans un ou plusieurs modes de boucle d'exécution et ne s'exécutent que lorsque la boucle d'exécution s'exécute dans l'un de ces modes. Les modes communs sont un ensemble de modes de boucle d'exécution pour lesquels vous pouvez définir un ensemble de sources, de temporisateurs et d'observateurs partagés par ces modes. Au lieu d'enregistrer une source, par exemple, dans chaque mode de boucle d'exécution spécifique, vous pouvez l'enregistrer une fois dans le pseudo-mode commun de la boucle d'exécution et elle sera automatiquement enregistrée dans chaque mode de boucle d'exécution dans l'ensemble de modes communs. De même, lorsqu'un mode est ajouté à l'ensemble des modes communs, toutes les sources, minuteries ou observateurs déjà enregistrés dans le pseudo-mode commun sont ajoutés au mode commun nouvellement ajouté.

Quelqu'un peut-il expliquer les deux en langage humain?

101
Stkim1

Une boucle d'exécution est un mécanisme qui permet au système de réveiller les threads en veille afin qu'ils puissent gérer les événements asynchrones. Normalement, lorsque vous exécutez un thread (à l'exception du thread principal), il existe une option pour démarrer le thread dans une boucle d'exécution ou non. Si le thread exécute une opération de tri ou de longue durée sans interaction avec des événements externes et sans temporisation, vous n'avez pas besoin d'une boucle d'exécution, mais si votre thread doit répondre aux événements entrants, il doit être attaché à une boucle d'exécution afin de réveillez le fil quand de nouveaux événements arrivent. C'est le cas des threads générés par NSURLConnection, car ils ne se réveillent que sur les événements entrants (depuis le réseau).

Chaque thread peut être associé à plusieurs boucles d'exécution, ou peut être associé à une boucle d'exécution spécifique qui peut être définie pour fonctionner dans différents modes. Un "mode de boucle d'exécution" est une convention utilisée par le système d'exploitation pour établir certaines règles concernant le moment de livrer certains événements ou de les collecter pour les remettre ultérieurement.

Habituellement, toutes les boucles d'exécution sont définies sur le "mode par défaut" qui établit un moyen par défaut de gérer les événements d'entrée. Par exemple: dès qu'un événement de glissement de souris (Mac OS) ou tactile (sur iOS) se produit, le mode de cette boucle d'exécution est défini sur le suivi des événements; cela signifie que le thread ne sera pas réveillé lors de nouveaux événements réseau, mais ces événements seront livrés plus tard lorsque l'événement d'entrée utilisateur se terminera et la boucle d'exécution sera de nouveau définie sur le mode par défaut; il s'agit évidemment d'un choix fait par les architectes du système d'exploitation pour donner la priorité aux événements utilisateur plutôt qu'aux événements d'arrière-plan.

Si vous décidez de changer le mode de boucle d'exécution pour votre thread NSURLConnection, en utilisant scheduleInRunLoop:forModes:, vous pouvez alors affecter le thread à une boucle d'exécution spéciale mode, plutôt qu'à la boucle d'exécution par défaut spécifique. Le pseudo-mode spécial appelé NSRunLoopCommonModes est utilisé par de nombreuses sources d'entrée, y compris le suivi des événements. Par exemple, affecter l'instance de NSURLConnection au mode commun signifie associer ses événements au "mode de suivi" en plus du "mode par défaut". Un avantage/inconvénient de l'association de threads à NSRunLoopCommonModes est que le thread ne sera pas bloqué par les événements tactiles.

De nouveaux modes peuvent être ajoutés aux modes communs, mais il s'agit d'une opération de bas niveau.

Je voudrais terminer en ajoutant quelques notes:

  • En règle générale, nous devons utiliser un ensemble d'images ou de miniatures téléchargées depuis le réseau avec une vue sous forme de tableau. Nous pouvons penser que le téléchargement de ces images à partir du réseau pendant que la vue de la table défile pourrait améliorer l'expérience utilisateur (car nous pouvions voir les images pendant le défilement), mais ce n'est pas avantageux car la fluidité du défilement peut en souffrir considérablement. Dans cet exemple avec NSURLConnection, une boucle d'exécution ne doit pas être utilisée; il serait préférable d'utiliser les méthodes déléguées UIScrollView pour détecter la fin du défilement, puis mettre à jour la table et télécharger de nouveaux éléments à partir du réseau;

  • Vous pouvez envisager d'utiliser GCD qui vous aidera à "protéger" votre code des problèmes de gestion de boucle d'exécution. Dans l'exemple ci-dessus, vous pouvez envisager d'ajouter vos demandes réseau à une file d'attente série personnalisée.

187
viggio24