ios 同步异步消息

通知的同步发送

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
- (void)viewDidLoad
{
    [super viewDidLoad];
  // Do any additional setup after loading the view, typically from a nib.

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(receiveNotification:) name:@"notice" object:nil];

    [self sendNotification];
}

- (void)sendNotification
{
    [[NSNotificationCenter defaultCenter] postNotificationName:@"notice" object:nil userInfo:@{@"key1": @"hello", @"key2":@"bye"}];
    NSLog(@"sendNotification");
}

- (void)receiveNotification:(NSNotification *)notification
{
    NSDictionary *userinfo = [notification userInfo];
    NSLog(@"%@", userinfo);
}

如上代码,如果给发送通知的方法sendNotification和接受通知的方法receiveNotification打上断点,可看到他们在统一线程中,观察控制台输出内容:

1
2
3
4
5
2014-03-27 21:14:59.913 testNoti[726:60b] {
    key1 = hello;
    key2 = bye;
}
2014-03-27 21:14:59.915 testNoti[726:60b] sendNotification

可看出发送通知的机制采用的是同步的方式。

通知的异步发送

通知异步发送使用的是NSNotificationQueue,如下:

1
[[NSNotificationQueue defaultQueue] enqueueNotification:[NSNotification notificationWithName:@"notice" object:nil] postingStyle:NSPostWhenIdle coalesceMask:NSNotificationNoCoalescing forModes:@[NSRunLoopCommonModes, NSDefaultRunLoopMode]];
  1. 参数notification:通知对象。
  2. 参数postingStyle:表示让通知队列在什么情况下发出此通知。

    NSPostASAP:ASAP(As soon as possible)表示在当前消息循环的最近一次循环完成后发送通知。
    NSPostWhenIdle:表示让队列在当前消息空闲时发送。
    NSPostNow:表示让队列立即发送。
    
  3. 参数coalesceMask:过滤重复通知的方式,可以通过使用或运算使用多重情况:

    NSNotificationNoCoalescing:表示不过滤重复的通知
    NSNotificationCoalescingOnName:过滤相同名字的通知
    NSNotificationCoalescingOnSender:过滤相同对象指针的通知
    
  4. 参数modes:指定消息循环模式,只用在当前消息循环和参数中的消息循环一直时,通知才会适时发出。在iOS中只有两种可用的循环模式:NSRunLoopCommonModesNSDefaultRunLoopMode

注意

如果实在主线程使用通知队列发送通知,就不会出现什么问题。但是如果在子线程中异步发送通知,则可能出现通知被取消的情况。对于通知队列来说,如果需要发送的通知的所在线程在发送前就结束了,通知队列会取消该通知。

我们可以使用NSTimer或者NSMachPort对象让消息循环循环地监视等待,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
@interface XYViewController ()

@property (nonatomic, strong) NSMachPort *notificationPort;
@end

@implementation XYViewController
{
    BOOL _bFinishNotification;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(receiveNotification:) name:@"test" object:nil];

    [NSThread detachNewThreadSelector:@selector(sendNotification) toTarget:self withObject:nil];
}

- (void)sendNotification
{
    @autoreleasepool {
        _bFinishNotification = NO;

        self.notificationPort = [[NSMachPort alloc] init];
        [self.notificationPort setDelegate:self];
        [[NSRunLoop currentRunLoop] addPort:self.notificationPort forMode:NSDefaultRunLoopMode];

        [[NSNotificationQueue defaultQueue] enqueueNotification:[NSNotification notificationWithName:@"test" object:nil] postingStyle:NSPostWhenIdle coalesceMask:NSNotificationNoCoalescing forModes:@[NSRunLoopCommonModes, NSDefaultRunLoopMode]];

        while (!_bFinishNotification) {
            [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
        }
    }
}

- (void)receiveNotification:(NSNotification *)notification
{
    NSLog(@"received");

    _bFinishNotification = YES;
    [self.notificationPort sendBeforeDate:[NSDate date] components:nil from:nil reserved:0];
}

- (void)handleMachMessage:(void *)msg
{
    NSLog(@"port message received");
}

—-End—–

参考资料: 《深入浅出Objective-c》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值