关于通知,最近在工作和学习中遇到了3个不太清楚的地方,经过网上查资料,和自我琢磨,终于把他该清楚了,现在分享给大家。
一.实例
首先建立一个测试案例。新建新建一个项目,在StoryBoard上托一个导航控制器为初始化控制器,其更控制器为一个TableViewController,在其根控制器上再连接一个ViewController,ViewController类上代码如下:
1 - (void)viewDidLoad { 2 [super viewDidLoad]; 3 4 // 添加观察 5 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textChanged:) name:UITextFieldTextDidChangeNotification object:nil]; 6 } 7 8 - (void)dealloc { 9 NSLog(@"88"); 10 } 11 12 - (void)textChanged:(NSNotification *)n { 13 14 NSLog(@"睡 %@", [NSThread currentThread]); 15 [NSThread sleepForTimeInterval:1.0]; 16 17 static int num = 0; 18 NSLog(@"%@ %d", n, num++); 19 } 20 21 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { 22 // 发送通知 23 [[NSNotificationCenter defaultCenter] postNotificationName:UITextFieldTextDidChangeNotification object:@"hello"]; 24 25 NSLog(@"come here"); 26 }
查询底层代码,可以看到通知是一个常量字符串。因此可以得到结论,通知中心本质上监听的是一个"字符串"
UIKIT_EXTERN NSString *const UITextFieldTextDidChangeNotification;
当程序运行后,导航栏左边按钮,初始化ViewController,单击屏幕,然后再点击返回按钮,返回导航控制器根控制器。
运行结果如下:
从运行结果中可以得到两个结论:
come here是最后输出的,因此可以确定通知是同步的。
当点击返回按钮时,dealloc执行,并输出"88",因此可以确定不删除观察者,程序也不会奔溃。
但是仔细分析会发现,但是通知中心注册的仍然存在,事件发生的时候,仍然会广播,会有潜在的风险
1> vc 第一次实例化:0x0000abcd,在通知中心注册了,当发生事件的时候,通知中心会广播
2> pop 出去,vc 被释放,通知中心并没有要求必须删除观察者
3> vc 又一次被实例化:0x0000dcab,事件发生时,通知中心会继续广播给两个地址,有可能程序会崩溃
二.小结
- 通知中心本质上监听的是一个"字符串"。
- 通知是同步的,原因和 KVO 是一样的,保证所有的监听者能够及时作出响应!
- 通知结束后,一定要删除观察者!