关于this question我想知道是否有任何普遍接受的逻辑关于何时使用NSNotification,在主线程中使用观察者,使用GCD将工作从后台线程调度到主线程?
似乎通过通知 - 观察者设置,您必须记住在视图卸载时拆除观察者,然后您可靠地忽略通知,其中将作业分派给主线程可能导致块被执行时视图已被卸载。
因此,在我看来,通知应该提供更好的应用稳定性。我假设调度选项提供了比我读过的GCD更好的性能吗?
更新
我知道通知和发送可以一起愉快地工作,在某些情况下,应该一起使用。我试图找出是否存在应该/不应该使用的特定情况。
示例案例:为什么我会选择主线程来从调度块中发出通知,而不是仅仅调度主队列上的接收函数? (显然在这两种情况下接收功能会有一些变化,但最终结果似乎是相同的)。
答案 0 :(得分:14)
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...
});
}
当然,在这个例子中你可能根本就不在背景线程上发布通知,但是如果你使用的框架不能保证它会在哪个线程上发布通知,这可能会派上用场。