NSNotification vs dispatch_get_main_queue

En relation avec cette question, je me demandais s'il y avait une logique généralement acceptée concernant le moment d'utiliser NSNotification, avec un observateur dans votre thread principal, vs l'utilisation de GCD pour répartir le travail d'un thread d'arrière-plan au thread principal?

Il semble qu'avec une configuration d'observateur-notification, vous devez vous callbacker d'abattre l'observateur lorsque votre vue est déchargée, mais vous ignorez la notification de manière fiable, où l'envoi d'un travail au thread principal peut entraîner l'exécution d'un bloc lorsque la vue été déchargé.

En tant que tel, il me semble que les notifications devraient améliorer la stabilité de l'application. Je suppose que l'option d'expédition fournit une meilleure performance de ce que j'ai lu de GCD?

METTRE À JOUR:

Je suis conscient que les notifications et l'envoi peuvent fonctionner set et, dans certains cas, devraient être utilisés set. J'essaie de savoir s'il y a des cas particuliers où l'on devrait / ne devrait pas être utilisé.

Un exemple de cas: Pourquoi devrais-je sélectionner le thread principal pour triggersr une notification à partir d'un bloc dissortingbué plutôt que d'envoyer la fonction de réception dans la queue principale? (Évidemment, il y aurait des changements à la fonction de réception dans les deux cas, mais le résultat final semblerait être le même).

Le NSNotificationCenter et gcd & dispatch_get_main_queue() servent des objectives très différents. Je ne sais pas "vs" est vraiment applicable.

NSNotificationCenter fournit un moyen de NSNotificationCenter des parties disparates de votre application. Par exemple, le kReachabilityChangedNotification dans l'exemple de code d' kReachabilityChangedNotification d'Apple est enregistré dans le centre de notifications lorsque l'état du réseau du système change. Et à votre tour, vous pouvez requestr au centre de notification d'appeler votre sélecteur / invocation afin que vous puissiez répondre à un tel événement. (Think Air Raid Siren)

gcd autre part, gcd fournit un moyen rapide d'assigner le travail à faire sur une queue spécifiée par vous. Il vous permet de dire au système les points auxquels votre code peut être disséqué et traité séparément pour tirer parti des multi-threads et des CPU multi-core.

Généralement (presque toujours) les notifications sont observées sur le fil sur lequel ils sont postés. À l'exception notable d'une pièce d'API …

La seule partie de l'API où ces concepts se croisent est celle de NSNotificationCenter :

 addObserverForName:object:queue:usingBlock: 

C'est essentiellement une méthode pratique pour s'assurer qu'une notification donnée est observée sur un thread donné. Bien que le paramètre " usingBlock " usingBlock que derrière les scènes il utilise gcd .

Voici un exemple de son utilisation. Supposons que quelque part dans mon code il y ait un NSTimer appelant cette méthode chaque seconde:

 -(void)timerTimedOut:(NSTimer *)timer{ dispatch_async(dispatch_get_global_queue(0, 0), ^{ // Ha! Gotcha this is on a background thread. [[NSNotificationCenter defaultCenter] postNotificationName:backgroundColorIsGettingBoringNotification object:nil]; }); } 

Je veux utiliser le backgroundColorIsGettingBoringNotification comme un signal pour moi de changer la couleur d'arrière-plan de ma vue de controller de vue. Mais il est posté sur un fil de fond. Eh bien, je peux utiliser l'API mentionnée ci-dessus pour observer cela uniquement sur le fil principal. Notez viewDidLoad dans le code suivant:

 @implementation NoWayWillMyBackgroundBeBoringViewController { id _observer; } -(void)observeHeyNotification:(NSNotification *)note{ static NSArray *rainbow = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ rainbow = @[[UIColor redColor], [UIColor orangeColor], [UIColor yellowColor], [UIColor greenColor], [UIColor blueColor], [UIColor purpleColor]]; }); NSInteger colorIndex = [rainbow indexOfObject:self.view.backgroundColor]; colorIndex++; if (colorIndex == rainbow.count) colorIndex = 0; self.view.backgroundColor = [rainbow objectAtIndex:colorIndex]; } - (void)viewDidLoad{ [super viewDidLoad]; self.view.backgroundColor = [UIColor redColor]; __weak PNE_ViewController *weakSelf = self; _observer = [[NSNotificationCenter defaultCenter] addObserverForName:backgroundColorIsGettingBoringNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note){ [weakSelf observeHeyNotification:note]; }]; } -(void)viewDidUnload{ [super viewDidUnload]; [[NSNotificationCenter defaultCenter] removeObserver:_observer]; } -(void)dealloc{ [[NSNotificationCenter defaultCenter] removeObserver:_observer]; } - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation{ return (interfaceOrientation == UIInterfaceOrientationPortrait); } @end 

Le principal avantage de cette API semble être que votre bloc d'observation sera appelé lors de l'appel postNotification... Si vous avez utilisé l'API standard et implémenté observeHeyNotification: comme ce qui suit, il n'y aurait aucune garantie quant à la durée avant que votre bloc d'expédition soit exécuté:

 -(void)observeHeyNotification:(NSNotification *)note{ dispatch_async(dispatch_get_main_queue(), ^{ // Same stuff here... }); } 

Bien sûr, dans cet exemple, vous pouvez simplement ne pas publier la notification sur un thread d'arrière-plan, mais cela peut s'avérer utile si vous utilisez un framework qui ne garantit pas sur quel thread il va publier des notifications.