通知的同步发送
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]];
|
- 参数notification:通知对象。
-
参数postingStyle:表示让通知队列在什么情况下发出此通知。
NSPostASAP:ASAP(As soon as possible)表示在当前消息循环的最近一次循环完成后发送通知。
NSPostWhenIdle:表示让队列在当前消息空闲时发送。
NSPostNow:表示让队列立即发送。
-
参数coalesceMask:过滤重复通知的方式,可以通过使用或运算使用多重情况:
NSNotificationNoCoalescing:表示不过滤重复的通知
NSNotificationCoalescingOnName:过滤相同名字的通知
NSNotificationCoalescingOnSender:过滤相同对象指针的通知
-
参数modes:指定消息循环模式,只用在当前消息循环和参数中的消息循环一直时,通知才会适时发出。在iOS中只有两种可用的循环模式:NSRunLoopCommonModes
和NSDefaultRunLoopMode
。
注意
如果实在主线程使用通知队列发送通知,就不会出现什么问题。但是如果在子线程中异步发送通知,则可能出现通知被取消的情况。对于通知队列来说,如果需要发送的通知的所在线程在发送前就结束了,通知队列会取消该通知。
我们可以使用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》