Il NSNotificationCenter
e gcd
& dispatch_get_main_queue()
servono a scopi molto diversi. Io non faccio "contro" è veramente applicabile.
NSNotificationCenter
fornisce un modo di parti disparate de-accoppiamento della vostra applicazione. Ad esempio, lo kReachabilityChangedNotification
nel codice di esempio Reachability di Apple viene registrato nel centro notifiche quando lo stato della rete del sistema cambia. E a sua volta puoi chiedere al centro notifiche di chiamare il tuo selettore/invocazione in modo da poter rispondere a tale evento. (Think Air Raid Siren)
gcd
d'altra parte fornisce un modo rapido di assegnare il lavoro da fare su una coda specificata da te. Ti consente di dire al sistema i punti in cui il tuo codice può essere sezionato e elaborato separatamente per trarre vantaggio da thread multipli e da CPU multi-core.
generale (quasi sempre) le notifiche si osservano sul filo su cui sono stati scritti. Con l'eccezione di un pezzo di API ...
L'unico pezzo di API dove questi concetti intersecano è NSNotificationCenter
's:
addObserverForName:object:queue:usingBlock:
Questo è essenzialmente un metodo conveniente per assicurare che una determinata notifica è osservato su un dato thread. Sebbene il parametro "usingBlock
" dia via che dietro le quinte sta usando gcd
.
Ecco un esempio del suo utilizzo. Supponiamo che da qualche parte nel mio codice compare un NSTimer
di chiamare questo metodo ogni secondo:
-(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];
});
}
voglio usare il backgroundColorIsGettingBoringNotification
come un segnale per me di cambiare il colore di sfondo della vista di mio controller della vista. Ma è pubblicato su un thread in background. Bene, posso usare la suddetta API per osservare che solo sul thread principale.Nota viewDidLoad
nel codice seguente:
@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
Il vantaggio principale di questa API sembra essere che il vostro blocco di osservazione sarà chiamata durante la chiamata postNotification...
. Se è stato utilizzato l'API standard ed implementato observeHeyNotification:
come la seguente non ci sarebbe alcuna garanzia per quanto tempo sarebbe passato prima che è stato eseguito il tuo blocco la spedizione:
-(void)observeHeyNotification:(NSNotification *)note{
dispatch_async(dispatch_get_main_queue(), ^{
// Same stuff here...
});
}
Naturalmente in questo esempio si potrebbe semplicemente non inviare la notifica su un thread in background, ma questo potrebbe tornare utile se si utilizza un framework che non fornisce garanzie su quale thread invierà le notifiche.
Queste non sono opzioni che si escludono a vicenda. È possibile utilizzare GCD per lavorare su un thread in background, quindi tornare al thread principale e inviare una NSNotification (che viene ricevuta sullo stesso thread da cui viene inviata). O non capisco la domanda? – Kitsune
@Kitsune Mi rendo conto che i due possono essere usati tranquillamente insieme, sono curioso di sapere se ci sono casi ben noti in cui l'uno o l'altro è sempre usato/evitato. Ho cercato esempi in cui GCD è costantemente utilizzato per inviare lavoro a un thread in background, ma a volte vengono utilizzate notifiche per tornare al thread principale e altre volte, GCD viene utilizzato per tornare al thread principale. – Endophage
Sapete che le notifiche sono consegnate sullo stesso thread in cui sono state pubblicate? Quindi non possono essere utilizzati per "tornare al thread principale"! – Felix