一愉豺、主線程開啟通知中心
在主線程發(fā)送通知是同步的允乐,執(zhí)行順序 before矮嫉、ing、after牍疏。
- (void)viewDidLoad {
[super viewDidLoad];
//注冊通知
//object傳nil蠢笋,表示,接受所有名字為notifyName的通知鳞陨,否則只接受指定object對象的通知昨寞。
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleNotifi:) name:@"notifyName" object:nil];
}
- (void)handleNotifi:(NSNotification*)notifi{
NSLog(@"ing");
NSLog(@"%s",__func__);
}
- (IBAction)btnClicked:(id)sender {
NSLog(@"before");
//發(fā)送消息
[[NSNotificationCenter defaultCenter] postNotificationName:@"notifyName" object:nil];
NSLog(@"after");
}
在dealloc中移除通知中心。注:在控制器中注冊了一個消息中心,可以不用在dealloc中移除通知援岩,因為控制器自動執(zhí)行了這一操作歼狼。如果,自己創(chuàng)建一個類享怀,繼承于NSObject類羽峰,需要手動移除通知,否則會在iOS9以下的系統(tǒng)里崩潰凹蜈。
//移除所有的通知
- (void)removeObserver:(id)observer;
//移除指定的通知
- (void)removeObserver:(id)observer name:(nullable NSNotificationName)aName object:(nullable id)anObject;
二、子線程中開啟通知中心
執(zhí)行的順序是before忍啸、after仰坦、ing。
- (void)viewDidLoad {
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleNotifi:) name:@"notifyName" object:nil];
}
- (void)handleNotifi:(NSNotification *)notify{
NSLog(@"ing");
}
- (IBAction)btnClicked:(id)sender {
NSLog(@"before");
[NSThread detachNewThreadWithBlock:^{
[[NSNotificationCenter defaultCenter] postNotificationName:@"notifyName" object:nil userInfo:@{@"name":@"ads"}];
}];
NSLog(@"after");
}
三计雌、在主線程中用通知隊列的形式開啟通知
執(zhí)行順序:before悄晃、after、ing
- (void)viewDidLoad {
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleNotifi:) name:@"notifyName" object:nil];
}
- (void)handleNotifi:(NSNotification *)notify{
NSLog(@"ing = %@",[NSThread currentThread]);
}
- (IBAction)btnClicked:(id)sender {
[self notiQueue];
}
- (void)notiQueue{
NSLog(@"before");
NSNotificationQueue * notiQueue = [NSNotificationQueue defaultQueue];
NSNotification * noti = [NSNotification notificationWithName:@"notifyName" object:self userInfo:@{@"userInfo":@"name1"}];
//將通知放入隊列中凿滤,先進先出FIFO
//NSPostWhenIdle 空閑時發(fā)送
//NSPostASAP as soon as posible 盡快發(fā)送 當前runloop不是同一個mode,現(xiàn)等待一個runloop模式完后妈橄,就會執(zhí)行通知事件
//NSPostNow 馬上執(zhí)行
[notiQueue enqueueNotification:noti postingStyle:NSPostWhenIdle coalesceMask:NSNotificationCoalescingOnName forModes:nil];
NSLog(@"after");
}
四、在子線程中用通知隊列開啟通知
執(zhí)行順序:before翁脆、after
怎么不執(zhí)行handleNotifi呢眷蚓?原因:runloop沒有資源。
- (void)viewDidLoad {
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleNotifi:) name:@"notifyName" object:nil];
}
- (void)handleNotifi:(NSNotification *)notify{
NSLog(@"ing = %@",[NSThread currentThread]);
}
- (IBAction)btnClicked:(id)sender {
[NSThread detachNewThreadWithBlock:^{
[self notiQueue];
}];
}
- (void)notiQueue{
NSLog(@"before");
NSNotificationQueue * notiQueue = [NSNotificationQueue defaultQueue];
NSNotification * noti = [NSNotification notificationWithName:@"notifyName" object:self userInfo:@{@"userInfo":@"name1"}];
//將通知放入隊列中反番,先進先出FIFO
//NSPostWhenIdle 空閑時發(fā)送
//NSPostASAP as soon as posible 盡快發(fā)送 當前runloop不是同一個mode,現(xiàn)等待一個runloop模式完后沙热,就會執(zhí)行通知事件
//NSPostNow 馬上執(zhí)行
[notiQueue enqueueNotification:noti postingStyle:NSPostWhenIdle coalesceMask:NSNotificationCoalescingOnName forModes:[NSArray arrayWithObjects:NSDefaultRunLoopMode,nil]];
NSLog(@"after");
}
將runloop中添加資源,NSLog(@"runloop over"); 永遠不會被執(zhí)行罢缸。每次點擊按鈕篙贸,開啟通知,每次點擊都會多產(chǎn)生一條線程枫疆,這樣子會產(chǎn)生資源浪費爵川。
執(zhí)行順序:before、after息楔、ing寝贡。
- (void)notiQueue{
NSLog(@"before");
NSNotificationQueue * notiQueue = [NSNotificationQueue defaultQueue];
NSNotification * noti = [NSNotification notificationWithName:@"notifyName" object:self userInfo:@{@"userInfo":@"name1"}];
//將通知放入隊列中,先進先出FIFO
//NSPostWhenIdle 空閑時發(fā)送
//NSPostASAP as soon as posible 盡快發(fā)送 當前runloop不是同一個mode,現(xiàn)等待一個runloop模式完后值依,就會執(zhí)行通知事件
//NSPostNow 馬上執(zhí)行
[notiQueue enqueueNotification:noti postingStyle:NSPostWhenIdle coalesceMask:NSNotificationCoalescingOnName forModes:[NSArray arrayWithObjects:NSDefaultRunLoopMode,nil]];
NSLog(@"after");
NSPort * port = [[NSPort alloc] init];
[[NSRunLoop currentRunLoop] addPort:port forMode:NSRunLoopCommonModes];
[[NSRunLoop currentRunLoop] run];
NSLog(@"runloop over");
}
五兔甘、在指定線程上處理
通過NSPort讓通知在指定線程上執(zhí)行呢?如果將NSPort 放在主線程鳞滨,那么通知就會在主線程上執(zhí)行洞焙,將NSPort加在子線程上通知事件就會在子線程。
- (void)viewDidLoad {
[super viewDidLoad];
myPort = [[NSPort alloc] init];
[myPort setDelegate:self];
//放到子線程上
[NSThread detachNewThreadWithBlock:^{
[[NSRunLoop currentRunLoop] addPort:myPort forMode:NSDefaultRunLoopMode];
[[NSRunLoop currentRunLoop] run];
}];
//放在主線程上
//[[NSRunLoop currentRunLoop] addPort:myPort forMode:NSDefaultRunLoopMode];
}
- (void)handlePortMessage:(NSPortMessage *)message{
NSObject * obj = (NSObject *)message;
NSLog(@"%@",[NSThread currentThread]);
NSLog(@"message = %@",[obj valueForKey:@"msgid"]);
}
- (void)myPort{
[myPort sendBeforeDate:[NSDate date] msgid:111 components:nil from:nil reserved:0];
}
- (IBAction)btnClicked:(id)sender {
[self myPort];
}