iOS學習筆記6-關於NSNotificationCenter及同步非同步
iOS 提供了一種 “同步的” 訊息通知機制NSNotificationCenter,觀察者只要向訊息中心註冊, 即可接受其他物件傳送來的訊息,訊息傳送者和訊息接受者兩者可以互相一無所知,完全解耦。
基於這點,我們可以用來兩個物件之間的通訊!
注意,每個執行中的application都有一個NSNotificationCenter的單例,如原始碼:
+ (NSNotificationCenter *)defaultCenter;
只要任何一個物件註冊訊息通知,如果該訊息被髮送,那麼該物件將能夠收到訊息通知;從而實現在這個物件去執行另外一個物件的函式;
使用方法:
1. 觀察者註冊訊息通知
- (void)addObserver:(id)notificationObserver
selector:(SEL)notificationSelector
name:(NSString *)notificationName
object:(id)notificationSender
addObserver(觀察者) : self
selector(收到訊息後要執行的函式): notificationSelector
name (訊息通知的名字): notificationName
object (訊息傳送者) : 表示接收哪個傳送者的通知,如果第四個引數為nil,接收所有傳送者的通知
使用例項:
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleNotification:) name:TEST_NOTIFICATION object:nil];
注意的問題:
(1)Observer不能為nil;
(2 )如果name設定為nil,則表示接收所有訊息;
(3)監聽同一條通知的多個觀察者,在通知到達時,它們執行回撥的順序是不確定的,所以我們不能去假設操作的執行會按照新增觀察者的順序來執行
2. 傳送訊息通知(與觀察者註冊訊息通知對應)
- postNotification :
– postNotificationName:object:
– postNotificationName:object:userInfo:
我們可以根據需要指定通知的傳送者(object)並附帶一些與通知相關的資訊(userInfo),當然這些傳送者和userInfo(注意,這裡userInfo是個字典)可以封裝在一個NSNotification物件中,由- postNotification:來發送。注意,- postNotification:的引數不能為空,否則會引發一個異常
使用例項:
[[NSNotificationCenter defaultCenter] postNotificationName:TEST_NOTIFICATION object:nil];
這樣,就能夠實現在兩個類(或者一個類內回撥)之間的訊息通訊,可以理解成實現了回撥函式;
3.移除觀察者(與觀察者註冊訊息通知相對應)
- (void)removeObserver:(id)notificationObserver
- (void)removeObserver:(id)notificationObserver name:(NSString *)notificationName object:(id)notificationSender
(1)由於註冊觀察者時(不管是哪個方法),通知中心會維護一個觀察者的弱引用,所以在釋放物件時,要確保移除物件所有監聽的通知。否則,可能會導致程式崩潰或一些莫名其妙的問題。
(2)對於第二個方法,如果notificationName為nil,則會移除所有匹配notificationObserver和notificationSender的通知,同理notificationSender也是一樣的。而如果notificationName和notificationSender都為nil,則其效果就與第一個方法是一樣的了。大家可以試一下。
(3)最有趣的應該是這兩個方法的使用時機。–removeObserver:適合於在類的dealloc方法中呼叫,這樣可以確保將物件從通知中心中清除;而在viewWillDisappear:這樣的方法中,則適合於使用-removeObserver:name:object:方法,以避免不知情的情況下移除了不應該移除的通知觀察者。例如,假設我們的ViewController繼承自一個類庫的某個ViewController類(假設為SKViewController吧),可能SKViewController自身也監聽了某些通知以執行特定的操作,但我們使用時並不知道。如果直接在viewWillDisappear:中呼叫–removeObserver:,則也會把父類監聽的通知也給移除。
(4)關於註冊監聽者,還有一個需要注意的問題是,每次呼叫addObserver時,都會在通知中心重新註冊一次,即使是同一物件監聽同一個訊息,而不是去覆蓋原來的監聽。這樣,當通知中心轉發某一訊息時,如果同一物件多次註冊了這個通知的觀察者,則會收到多個通知。
4.關於同步非同步
預設的NSNotificationCenter是同步的,這是一般人忽略的地方,可以參考這篇好文 NSNotificationCenter的同步和非同步