IOS NSNotificationCenter 的坑
ios NSNotificationCenter訊息註冊與撤銷
一,使用defaultcenter。
簡單的情況下,若自己沒有太多的訊息需要註冊和處理,直接使用[NSNotificationCenter defaultCenter]來呼叫預設的訊息中心就夠用了。如果,有一些特殊的要求那麼,就需要試一下一個繼承自NSnotificationcenter的子類。
二,在檢視顯示的時候接受訊息。
有些時候,我們需要在一個已經顯示在主介面上的ViewController上做一點動作,比如當一個同步過程完成後,把同步的結果顯示在介面上。但是,如果這個ViewController沒有顯示在主介面上的話,它就不關心同步結果是什麼樣子了。所以這個時候,我們可以在viewwillappear或者viewdidapper中addobserver新增訊息監聽。然後在viewwilldisappear和viewDidDisappear中removeObserver把訊息登出掉。
三,在類的例項存在的時候接受訊息。
很多時候,我們需要讓一些類的例項只要在記憶體中,就要接受訊息,處理一些事情。比如我們有一個管理同步的類SyncManager,這個類使用了單例模式,從它alloc init之後就需要一些監聽同步的狀態,並作出處理。這個時候,我們就需要在重寫init函式,在其中註冊訊息。
- (id) init
{
self = [super init];
if(self)
{
[[NSNotificationCenter defaultCenter] addObserver........]
}
returnself;
}
然後在dealloc中登出
- (void) dealloc
{
......
[ [NSNotificationCenter defaultCenter] removeObserver.......]
[super dealloc]
}
四,在viewController存在的時候接受訊息
很多時候,我們會與ViewController打交道,甚至有些時候我們希望只要ViewController在記憶體中就監聽一些訊息作出一些動作。剛開始的時候,我想實現這個功能,我是這麼寫的
- (void) viewDidLoad
{
......
[[NSNotificationCenter defaultCenter] addObserver........]
.....
}
- (void) viewDidUnload
{
......
[ [NSNotificationCenter defaultCenter] removeObserver.......]
......
}
但是,在使用的過程中我發現viewDidLoad和Viewdidunload並不是成對出現的,只有在記憶體緊張和一些特定的情況下系統才會呼叫檢視的ViewDidUnload來解除安裝檢視。而ViewDIdload每一次載入都會執行。
也就是說removeObserver並不一定能夠被執行到,這就留下隱患。當檢視被dealloc之後,還在監聽訊息。最終會造成程式的崩潰。而且有些時候如果沒有在unload中removeOberver還會造成多次註冊同一個訊息。造成同一個函式執行多次。引起不必要的麻煩。
然後,在使用過程中,經過多次試驗我發現,使用init註冊訊息並在dealloc登出訊息最為合適,就像第三條說的那樣。在這裡值得提醒的一點是蘋果的官方文件上說:
The notification center does not retain its observers, therefore, you must ensure that you unregister observers (usingremoveObserver: or removeObserver:name:object:) before they are deallocated. (If you don't, you will generate a runtime error if the center sends a message to a freed object.)
意思是NotificationCenter並不會對Observer進行retain操作。因為就沒有必要對observer做多餘的release操作,而且,每一次註冊,必須對應一次登出,不然,程式死翹翹的事情就會來了。