NSNotification与dispatch_get_main_queue [英] NSNotification vs. dispatch_get_main_queue

查看:89
本文介绍了NSNotification与dispatch_get_main_queue的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

关于这个问题,我想知道是否普遍存在是否接受了关于何时使用NSNotification以及在主线程中使用观察者与使用GCD将工作从后台线程分派到主线程的逻辑?

In relation to this question I was wondering if there is any generally accepted logic regarding when to use NSNotification, with an observer in your main thread, vs using GCD to dispatch work from a background thread to the main thread?

似乎使用通知-观察者设置时,您必须记住要在视图卸载时拆下观察者,但随后您必须可靠地忽略该通知,因为将作业调度到主线程可能会导致在执行以下操作时执行块:该视图已被卸载.

It seems that with a notification-observer setup you have to remember to tear down the observer when your view unloads but then you reliably ignore the notification, where as dispatching a job to the main thread may result in a block being executed when the view has been unloaded.

因此,在我看来,通知应可改善应用程序的稳定性.我以为dispatch选项可提供比我读过的GCD更好的性能?

As such, it seems to me that notifications should provide improved app stability. I'm assuming that the dispatch option provides better performance from what I've read of GCD?

更新:

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

I'm aware that notifications and dispatch can work happily together and in some cases, should be used together. I'm trying to find out if there are specific cases where one should/shouldn't be used.

一个例子:为什么我要选择主线程来从分派的块中触发通知,而不是仅仅在主队列上分派接收函数? (显然,在两种情况下,接收功能都会有所变化,但最终结果似乎是相同的).

An example case: Why would I select the main thread to fire a notification from a dispatched block rather than just dispatching the receiving function on the main queue? (Obviously there would be some changes to the receiving function in the two cases, but the end result would seem to be the same).

推荐答案

NSNotificationCentergcd& dispatch_get_main_queue()用于非常不同的目的.我不认为"vs"是真正适用的.

The NSNotificationCenter and gcd & dispatch_get_main_queue() serve very different purposes. I don't thing "vs" is truly applicable.

NSNotificationCenter提供了一种将应用程序不同部分分离的方法.例如,当系统网络状态更改时,Apple可达性示例代码中的kReachabilityChangedNotification将发布到通知中心.然后,您可以要求通知中心调用您的选择器/调用,以便您可以响应此类事件.(想想空袭警报器)

NSNotificationCenter provides a way of de-coupling disparate parts of your application. For example the kReachabilityChangedNotification in Apple's Reachability sample code is posted to the notification center when the system network status changes. And in turn you can ask the notification center to call your selector/invocation so you can respond to such an event.(Think Air Raid Siren)

gcd提供了一种快速的方法来分配要在您指定的队列上完成的工作.它使您可以告诉系统可以分别解析和处理代码的点,以利用多线程和多核CPU的优势.

gcd on the other hand provides a quick way of assigning work to be done on a queue specified by you. It lets you tell the system the points at which your code can be dissected and processed separately to take advantage of multiple-threads and of multi-core CPUs.

通常(几乎总是)在发布通知的线程上观察到这些通知.除了一个API的显着例外...

Generally (almost always) the notifications are observed on the thread on which they are posted. With the notable exception of one piece of API...

与这些概念相交的一个API是NSNotificationCenter:

The one piece of API where these to concepts intersect is NSNotificationCenter's:

addObserverForName:object:queue:usingBlock:

从本质上讲,这是一种确保在给定线程上观察到给定通知的便捷方法.尽管"usingBlock"参数在幕后忽略了它,但它使用的是gcd.

This is essentially a convenient method for ensuring that a given notification is observed on a given thread. Although the "usingBlock" parameter gives away that behind the scenes it's using gcd.

这里是其用法的一个例子.假设在我的代码中某处每秒有一个NSTimer调用此方法:

Here is an example of its usage. Suppose somewhere in my code there is an NSTimer calling this method every second:

-(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:

I want to use the backgroundColorIsGettingBoringNotification as a signal to me to change my view controller's view's background color. But it's posted on a background thread. Well I can use the afore mentioned API to observe that only on the main thread. Note viewDidLoad in the following code:

@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:,将无法保证执行调度块之前需要花费多长时间:

The primary advantage of this API seems to be that your observing block will be called during the postNotification... call. If you used the standard API and implemented observeHeyNotification: like the following there would be no guarantee how long it would be before your dispatch block was executed:

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

当然,在此示例中,您不能简单地将通知发布到后台线程上,但是如果您使用的框架无法保证它将在哪个线程上发布通知,这可能会派上用场.

Of course in this example you could simply not post the notification on a background thread, but this might come in handy if you are using a framework which makes no guarantees about on which thread it will post notifications.

这篇关于NSNotification与dispatch_get_main_queue的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆