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.
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.
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.
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.