NSNotification是同步还是异步?

之前面试被问到NSNotification在发送通知的时候,是同步还是异步,当时自己真不清楚,然后这两天又遇到这个问题,自己写了代码测试一下。

代码如下:

#import "ViewController.h"

#define kNotificationName @"kNotificationName"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    // 初始化一个按钮
    UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(100, 100, 100, 50)];
    button.backgroundColor = [UIColor orangeColor];
    [button setTitle:@"触发通知" forState:UIControlStateNormal];
    [button addTarget:self action:@selector(buttonDown) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:button];

    // 注册通知
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(actionNotification:)
                                                 name:kNotificationName
                                               object:nil];

}

- (void) actionNotification: (NSNotification*)notification
{
    NSString* message = notification.object;
    NSLog(@"%@",message);

    sleep(3);

    NSLog(@"通知说话结束");
}

- (void)buttonDown
{
    [[NSNotificationCenter defaultCenter] postNotificationName:kNotificationName object:@"通知说话开始"];

    NSLog(@"按钮说话");
}

@end

点击按钮后,打印结果如下:

通过这里的时间间隔可以看出,在抛出通知以后,观察者在通知事件处理完成以后(这里我们休眠3秒),抛出者才会往下继续执行,也就是说这个过程默认是同步的;当发送通知时,通知中心会一直等待所有的observer都收到并且处理了通知才会返回到poster;


网上找了下,如果我们想改同步为异步,也是有办法的。

办法1:

让通知事件处理方法在子线程中执行,例如:

#import "ViewController.h"

#define kNotificationName @"kNotificationName"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    // 初始化一个按钮
    UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(100, 100, 100, 50)];
    button.backgroundColor = [UIColor orangeColor];
    [button setTitle:@"触发通知" forState:UIControlStateNormal];
    [button addTarget:self action:@selector(buttonDown) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:button];

    // 注册通知
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(actionNotification:)
                                                 name:kNotificationName
                                               object:nil];

}

- (void) actionNotification: (NSNotification*)notification
{
//    NSString* message = notification.object;
//    NSLog(@"%@",message);
//    
//    sleep(3);
//    
//    NSLog(@"通知说话结束");

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        NSString* message = notification.object;
        NSLog(@"%@",message);

        sleep(3);

        NSLog(@"通知说话结束:%@",[NSThread currentThread]);

    });
}

- (void)buttonDown
{
    [[NSNotificationCenter defaultCenter] postNotificationName:kNotificationName object:@"通知说话开始"];
    //    NSLog(@"按钮说话");
    NSLog(@"按钮说话:%@",[NSThread currentThread]);

}

@end

点击按钮后,打印结果如下:


办法2:

可以通过NSNotificationQueue的enqueueNotification: postingStyle:和enqueueNotification: postingStyle: coalesceMask: forModes: 方法将通告放入队列,实现异步发送,在把通告放入队列之后,这些方法会立即将控制权返回给调用对象。
我们修改按钮事件如下:

- (void)buttonDown
{
    NSNotification *notification = [NSNotification notificationWithName:kNotificationName
                                                                 object:@"通知说话开始"];
    [[NSNotificationQueue defaultQueue] enqueueNotification:notification
                                               postingStyle:NSPostASAP];

//    [[NSNotificationCenter defaultCenter] postNotificationName:kNotificationName object:@"通知说话开始"];

    NSLog(@"按钮说话");

}

点击按钮后,打印结果如下:

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值