web-dev-qa-db-fra.com

Quelle est la différence entre performSelectorOnMainThread et dispatch_async sur la file d'attente principale?

J'avais des problèmes pour modifier une vue à l'intérieur d'un fil. J'ai essayé d'ajouter une sous-vue, mais l'affichage a pris environ 6 secondes ou plus. Je l'ai finalement fait fonctionner, mais je ne sais pas comment exactement. Je me demandais donc pourquoi cela fonctionnait et quelle était la différence entre les méthodes suivantes:

//this worked -added the view instantly
dispatch_async(dispatch_get_main_queue(), ^{
    //some UI methods ej
    [view addSubview: otherView];
}

//this took around 6 or more seconds to display
[viewController performSelectorOnMainThread:@selector(methodThatAddsSubview:) withObject:otherView
 waitUntilDone:NO];

//Also didnt work: NSNotification methods -  took also around 6 seconds to display
//the observer was in the viewController I wanted to modify
//paired to a method to add a subview.
[[NSNotificationCenter defaultCenter] postNotificationName:
 @"notification-identifier" object:object];

Pour référence, cela a été appelé dans ce gestionnaire de complétion de la classe de ACAccountStore.

accountStore requestAccessToAccountsWithType:accountType withCompletionHandler:^(BOOL granted, NSError *error) {
            if(granted) {
            //my methods were here
            }
}

Edit: Quand je dis que cela ne fonctionnait pas, je voulais dire que l'affichage de la vue ajoutée prenait environ 6 secondes. 

52
Miguel Lomelí

Par défaut, -performSelectorOnMainThread:withObject:waitUntilDone: programme uniquement le sélecteur pour s'exécuter en mode d'exécution en boucle par défaut. Si la boucle d'exécution est dans un autre mode (par exemple, le mode de suivi), elle ne s'exécutera pas tant que la boucle d'exécution n'aura pas été réinitialisée. Vous pouvez contourner cela avec la variante -performSelectorOnMainThread:withObject:waitUntilDone:modes: (en passant tous les modes dans lesquels vous voulez qu'il soit exécuté).

Par contre, dispatch_async(dispatch_get_main_queue(), ^{ ... }) exécutera le bloc dès que la boucle d'exécution principale renverra le flux de contrôle dans la boucle d'événements. Il se fiche des modes. Donc, si vous ne voulez pas vous soucier des modes non plus, dispatch_async() peut être la meilleure solution.

70
Lily Ballard

C'est probablement parce que performSelectorOnMainThread:withObject:waitUntilDone: met en file d'attente le message avec les modes de boucle d'exécution courants. Selon Guide de programmation simultanée d'Apple , la file d'attente principale entrelace les tâches en file d'attente avec d'autres événements de la boucle d'exécution de l'application. Ainsi, si d’autres événements doivent être traités dans la file d’événements, les blocs en file d’attente de la file d’attribution peuvent être exécutés en premier, même s’ils ont été soumis ultérieurement.

Cet article est une excellente explication de performSelectorOnMainThread vs dispatch_async, qui répond également à la question ci-dessus.

1
Say2Manuj

Avez-vous essayé la PerformSelectorOnMainThread avec waitUntilDone=YES

Par exemple: 

Code:

[viewController performSelectorOnMainThread:@selector(methodThatAddsSubview:) withObject:otherView waitUntilDone:YES];

Je pense que cela pourrait résoudre le problème de savoir pourquoi la PerformSelectorOnMainThread prend si longtemps à répondre.

0
Ruchira Randana