该NSNotificationCenter
和gcd
& dispatch_get_main_queue()
服务非常不同的目的。我没有什么“vs”是真正适用的。
NSNotificationCenter
提供的应用程序的去耦不同部位的方式。例如,当Apple的Reachability示例代码中的kReachabilityChangedNotification
在系统网络状态更改时发布到通知中心。然后,您可以要求通知中心致电您的选择器/调用,以便您可以响应此类事件。(Think Air Raid Siren)
gcd
另一方面提供了一种快速分配工作的方法由您指定的队列。它可以让您告诉系统您的代码可以被分离和处理的位置,以便利用多线程和多核CPU。
一般(几乎总是)的通知其所发布的线程上观察到。采用一体成型的API显着的例外......
API的一个片而言,这些概念到相交是NSNotificationCenter
的:
addObserverForName:object:queue:usingBlock:
这实质上是确保一个给定的通知的简便方法在给定的线程上被观察到。虽然“usingBlock
”参数给出走在幕后它使用gcd
。
这里是其使用的一个例子。假设某个地方在我的代码有一个NSTimer
调用这个方法每秒:
-(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];
});
}
我想用backgroundColorIsGettingBoringNotification
作为一个信号,我改变我的视图控制器的视图的背景颜色。但它发布在后台线程上。那么我可以使用前面提到的API来观察,只有在主线程上。注意viewDidLoad
下面的代码:
@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
这个API的主要优点似乎是你的观察块将在postNotification...
通话过程中调用。如果您使用的是标准的API,并实现observeHeyNotification:
类似下面的就没有保证了执行您的调度块之前,这将是多么长:
-(void)observeHeyNotification:(NSNotification *)note{
dispatch_async(dispatch_get_main_queue(), ^{
// Same stuff here...
});
}
当然,在这个例子中,你可以根本就没有上张贴的通知后台线程,但如果您使用的框架不能保证在哪个线程上发布通知,这可能会派上用场。
这些并不是真正相互排斥的选择。你可以使用GCD在后台线程上工作,然后切换回主线程并发送一个NSNotification(它是从它发送的同一个线程上接收的)。或者我不理解这个问题? – Kitsune
@Kitsune我意识到这两个可以很愉快地一起使用,我只是好奇,如果有任何众所周知的情况下,其中一个或其他总是使用/避免。我一直在寻找GCD一直用于将工作发送到后台线程的示例,但有时会使用通知返回主线程和其他时间,GCD将用于返回到主线程。 – Endophage
你知道通知是在他们发布的同一个线程上传递的吗?所以他们不能用于“返回主线程”! – Felix