让人很纳闷的一个问题:通知是同步的还是异步的
在iOS开发中有人问“通知是同步的还是异步的”。个人感觉问的这个问题本身就有问题,你只能说通知的执行方法是同步的还是异步的,或者说发送通知是同步的还是异步的...对于通知是同步还是异步,这个问法本身就很笼统,让人不明白你是要问什么,所以很纳闷。
一个通知的小例子
这里我们用一个简单的小例子来看看通知的执行是在子线程还是在主线程。
1、 首先我们在viewDidLoad方法里面注册了一个通知:
- (void)viewDidLoad {
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(test) name:kTestNotificationName object:nil];
}
通知的注册者是self,执行方法是test,name是一个字符常量
static NSString *kTestNotificationName = @"TestNotification";
2、我们是在ViewController中测试的,借用touch方法来试试
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
dispatch_queue_t queue = dispatch_queue_create("CONCURRENT QUEUE", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
[[NSNotificationCenter defaultCenter] postNotificationName:kTestNotificationName object:nil];
NSLog(@"%@",[NSThread currentThread]);
});
}
这里我们先写了一个队列CONCURRENT QUEUE,然后执行异步任务。异步任务里面我们发送通知。
3、test方法里打印
- (void)test {
NSLog(@"test %@",[NSThread currentThread]);
}
4、打印结果
2017-08-07 16:55:16.987 Test[4333:191487] test <NSThread: 0x608000266e00>{number = 3, name = (null)}
2017-08-07 16:55:16.987 Test[4333:191487] <NSThread: 0x608000266e00>{number = 3, name = (null)}
- 打印结果显示我们是在子线程中发送的通知,则通知的执行方法也在子线程中执行。
- 如果将上述线程改成主线程中发送通知的话,通知执行方法就会在主线程中执行,主线程中打印结果如下:
2017-08-07 17:16:08.164 Test[4472:200122] test <NSThread: 0x60000007d6c0>{number = 1, name = main}
2017-08-07 17:16:08.165 Test[4472:200122] <NSThread: 0x60000007d6c0>{number = 1, name = main}
完整例子如下:
#import "ViewController.h"
static NSString *kTestNotificationName = @"TestNotification";
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
//注册,主线程
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(test) name:kTestNotificationName object:nil];
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
//创建队列
dispatch_queue_t queue = dispatch_queue_create("CONCURRENT QUEUE", DISPATCH_QUEUE_CONCURRENT);
//执行异步任务
dispatch_sync(queue, ^{
[[NSNotificationCenter defaultCenter] postNotificationName:kTestNotificationName object:nil];
NSLog(@"%@",[NSThread currentThread]);
});
}
- (void)test {
NSLog(@"test %@",[NSThread currentThread]);
}
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self name:kTestNotificationName object:nil];
}
@end
例子中测试子线程中发送通知,看通知方法是在哪个线程中执行;我们可以将异步任务改成同步任务,看看在主线程中发送通知,确认一下执行方法是在主线程。
总结
发送通知是在哪个线程,则执行通知的方法就在哪个线程中执行。
对于有些人说“通知都是异步的”,我想了想可能这指的是通知发送后找注册者的这个过程是异步的吧?是不是这样呢?