從 iOS 9 開始葡盗,即使不移除觀察者對象螟左,程序也不會出現(xiàn)異常。
對于addObserver:要分ViewController和普通NSObject兩個說起
ViewController:在調(diào)用ViewController的dealloc的時候觅够,系統(tǒng)會調(diào)用[[NSNotificationCenter defaultCenter]removeObserver:self]方法胶背,所以如果是在viewDidLoad中使用addObserver添加監(jiān)聽者的話可以省掉移除。
普通NSObject:在iOS9之后蔚约,NSObject也會像ViewController一樣在dealloc時調(diào)用[[NSNotificationCenter
defaultCenter]removeObserver:self]方法奄妨,在iOS9之前的不會調(diào)用,需要自己寫苹祟。
但是在使用類別的時候如果我們添加了通知砸抛,那么我們是沒有辦法在類別里面重寫dealloc的,如果不移除通知就會出現(xiàn)野指針树枫,這個時候我們就可以在iOS9以上使用addObserver直焙,將通知的移除交給系統(tǒng),iOS9一下使用addObserverForName+weakSelf砂轻,雖然通知依然存在奔誓,但是不會調(diào)用doSomeThing方法(不要直接在block里面寫處理過程啊)搔涝。
為什么 iOS 9 之前需要手動移除觀察者對象厨喂?
觀察者注冊時,通知中心并不會對觀察者對象做 retain 操作庄呈,而是對觀察者對象進(jìn)行unsafe_unretained 引用蜕煌。
什么是unsafe_unretained?因?yàn)?Cocoa 和 Cocoa Touch 中的一些類仍然還沒有支持 weak 引用诬留。所以斜纪,當(dāng)我們想對這些類使用弱引用的時候,只能用unsafe_unretained來替代文兑。
// for attribute
@property (unsafe_unretained) NSObject *unsafeProperty;
// for variables
NSObject *__unsafe_unretained unsafeReference;
不安全引用(unsafe reference)和弱引用 (weak reference) 類似盒刚,它并不會讓被引用的對象保持存活,但是和弱引用不同的是绿贞,當(dāng)被引用的對象釋放的時因块,不安全引用并不會自動被置為 nil,這就意味著它變成了野指針籍铁,而對野指針發(fā)送消息會導(dǎo)致程序崩潰贮聂。
因此靠柑,觀察者對象在釋放之前必須從通知中心移除引用,否則通知中心就會給野指針?biāo)玫膶ο蟀l(fā)送消息吓懈,導(dǎo)致程序崩潰歼冰。既然如此,為什么通知中心不對觀察者對象進(jìn)行弱引用呢耻警?我們剛才已經(jīng)提到隔嫡,Cocoa 和 Cocoa Touch 中的一些類還沒有支持弱引用,所以采用不安全的引用只是為了兼容舊的版本甘穿。
從 iOS 9 開始通知中心會對觀察者進(jìn)行弱引用腮恩,所以不需要在觀察者對象釋放之前從通知中心移除。但是温兼,通過-[NSNotificationCenter addObserverForName:object:queue:usingBlock]方法注冊的觀察者依然需要手動的釋放秸滴,因?yàn)橥ㄖ行膶λ鼈兂钟械氖菑?qiáng)引用。