1. 程式人生 > >iOS學習筆記6-關於NSNotificationCenter及同步非同步

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的同步和非同步