NSNotification与dispatch_get_main_queue

关于这个问题,我想知道是否有任何普遍接受的逻辑关于什么时候使用NSNotification,在你的主线程中使用观察者,还是使用GCD从后台线程派发工作到主线程?

看起来,通过观察器设置,你必须记得当你的视图卸载时拆掉观察者,但是你可靠地忽略了通知,当调度一个工作到主线程可能导致一个块被执行时,视图有被卸载。

因此,在我看来,通知应该会提高应用程序的稳定性。 我假设调度选项提供了我读过的GCD更好的性能?

更新:

我知道,通知和调度可以愉快地一起工作,在某些情况下,应该一起使用。 我试图找出是否有特定的情况下,应该/不应该使用。

一个例子:为什么我会select主线程来从调度块中发出通知,而不是只调度主队列上的接收函数? (显然在这两种情况下接收函数会有一些变化,但最终的结果看起来是一样的)。

NSNotificationCentergcddispatch_get_main_queue()用途完全不同。 我没有什么“vs”是真正适用的。

NSNotificationCenter提供了一种解耦应用程序不同部分的方法。 例如,当系统networking状态改变时,Apple Reachability示例代码中的kReachabilityChangedNotification会发布到通知中心。 反过来,你可以要求通知中心打电话给你的select器/调用,以便你可以回应这样的事件。(Think Air Raid Siren)

gcd另一方面提供了一个快速的方式分配工作要在你指定的队列上完成。 它可以让你告诉系统你的代码可以分解和处理的点,以利用multithreading和多核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... }); } 

当然,在这个例子中,你可以不通过后台线程发布通知,但是如果你使用的是一个框架,它不会保证在哪个线程上发布通知,这可能会派上用场。