2017.8.4更新
如果只需兼容iOS9.0和macOS10.11及其以后版本,不需要主动取消通知注册.如果有低版本支持的需求,请继续往下阅读.
NSNotification在什么情境下会引起Crash呢?一个稍有经验的开发者很快就能想到原因:一个对象注册了通知,在销毁时忘记取消注册.
在开发中,通知算是比较常用的.如何更好地使用通知,写出更健壮的代码,值得我们思考一下.
(取消)注册时机
在viewDidLoad进行注册通知的开发者应该不是少数.在这里注册,似乎不会有什么问题,毕竟view unload出现的可能性不是很大.作为开发者,我们要知道这种情况的存在.view是可以unload和reload的.
一旦view unload了,viewDidLoad就调用不止一次.一个对象多次注册通知,自然也会多次接收到通知.
在viewWill/DidAppear里注册,也会导致注册多次,除非在viewWill/DidDisappear取消注册.在viewWill/DidDisappear取消注册,会导致一个问题,页面进入下一级页面时就无法收到通知.
一般情况下,最合适的时机是在init方法注册,dealloc方法取消注册.
优雅取消注册的方式
应该有人像下面这样写取消注册的代码
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self name:kSomeNotificationName object:someObject];
...
}
这样写没问题.但是这样写,可维护性并不高.如果某天新加一个kSomeOtherNotificationName通知,忘了取消就会导致Crash.
下面这种写法,既简洁又避免了忘记取消新的通知注册问题.
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
主线程调用
我想不会有人在其他线程去取消注册,如果你真这么做,我也无话可说.在其他线程发送通知,会引起很多隐藏的bug.切记,发通知时一定要在主线程.