[iOS] Notification Programming Topics --- Registering for a Notification





此份文件為個人學習通知中心的翻譯,內文請參考蘋果官方文件,若有翻譯錯誤請見諒,請勿挪作商業用途,並著明出處。


你可以註冊以接收你自己應用程序的通知(參考"Registering for Local Notifications")或其他應用程序的通知("Registering for Distributed Notifications")。當你的物件釋放時(deallocated),要取消註冊接收通知(參考"Unregistering an Observer")。

Registering for Local Notifications

調用通知中心的addObserver:selector:name:object:方法來讓物件註冊接收通知,需指定觀察者(observer)、通知中心需傳送給觀察者的訊息、欲接收的通知名稱以及物件。你不需同時指定物件和名稱,若你只有指定物件,觀察者將接收所有包含那個物件的通知,若你只有指定通知名稱,觀察者將會接收每一次所貼出的通知而忽略與該通知有關的物件。

觀察者是可以對同樣的通知接收超過一個以上的訊息。在這個情況,觀察者將接收它所註冊要去接收的通知的所有訊息,但無法決定接收的順序。若你稍後決定某個觀察者不需再接收通知(舉例來說,若觀察者被釋放),你可以使用removeObserver: 或removeObserver:name:object:方法來將此觀察者從通知中新的觀察者列表中移除。正常來說你對程序(process)的預設通知中心註冊物件。你可以使用defaultCenter類別方法來獲得預設物件。一個使用通知中心來接收通知的例子,假設你想要在視窗變成主視窗時執行某個操作(舉例來說,給inspector panel實作一個控制器)。你可以註冊你的客制化物件為一個觀察者,如下例:

[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(aWindowBecameMain:)
name:NSWindowDidBecomeMainNotification object:nil];

將nil做為物件傳遞給觀察者,當任何物件貼出NSWindowDidBecomeMainNotification通知,客制化物件(self)會被知會。當視窗變成主要視窗(main),它貼一個NSWindowDidBecomeMainNotification到通知中心。通知中心調用這些觀察者在addObserver:selector:name:object:方法內的selector引數指定的方法來知會所有對這通知有興趣的觀察者。在我們的子中,selector是aWindowBecameMain:方法。aWindowBecameMain:方法可能實作如下:









 
- (void)aWindowBecameMain:(NSNotification *)notification {
 
NSWindow *theWindow = [notification object];
MyDocument = (MyDocument *)[[theWindow windowController] document];
// Retrieve information about the document and update the panel.
 
}

NSWindow物件不需知道任何有關你的inspector panel的事情。

Registering for Distributed Notifications


指定通知應送出的訊息、物件要接收的通知的名稱、需匹配的識別字串(物件引數)、以及若通知傳送被暫停(suspended)時該怎麼作(behavior to follow),送出addObserver:selector:name:object:suspensionBehavior:方法到一個NSDistributedNotificationCenter物件,物件本身可以將它自己註冊以接收通知。因為發布的物件和觀察者可能處於不同的程序(process)中,通知不可以包含指向任意物件的指標。因此,NSDistributedNotificationCenter類別需要通知使用NSString物件做為物件引數。通知匹配是基於此字串而不是物件指標。你應該檢查發布通知的物件的文檔,看看他用什麼做為識別字串。

當程序(process)不再有興趣立即收到通知,它(應指process)可能暫停通知傳遞,這通常是於應用程式被隱藏或是被放到背景時。(當應用程式非啟動(inactive)時,NSApplication物件自動暫停傳遞)。addObserver方法裡面的suspensionBehavior引數確認當傳遞暫停時如何處理到達(arriving)的通知。有四種不同種類的暫停行為,每一個用於不同的環境:

NSNotificationSuspensionBehaviorDrop
直到Server接收到setSuspended:NO 訊息,否則Server不會讓任何有這個名稱和物件的通知列隊(queue)。

NSNotificationSuspensionBehaviorCoalesce
Server只讓特定名稱和物件的最新一次的通知列隊(queue),比較早的通知都會捨棄。在暫停行為沒有明確的於引數中指出的cover method內,NSNotificationSuspensionBehaviorCoalesce是預設值。

NSNotificationSuspensionBehaviorHold
直到隊伍(queue)排滿(隊伍大小由server決定),server保存所有匹配的通知,此時,server可能會刷新(flush)列隊通知(queued notification)。

NSNotificationSuspensionBehaviorDeliverImmediately
Server會傳遞匹配註冊的通知,不論它是否接收到setSuspended:YES訊息。當匹配這個暫停行為的通知時,它會先讓任何列中的通知刷新。效果是好像於應用程序暫停期間server收到setSuspendedNO,隨後進行交付問題的通知,然後回到以前的暫停或取消暫停狀態。


你可藉著傳送setSuspended:YES到distributed通知中心來將通知暫停。在通知被暫停時,通知server會處理以依據觀察者註冊接收通知時所指明的暫停行為之暫停通知傳送之程序(process)的通知。當程序(process)啟動通知傳遞,所有列隊好的通知都會立刻被傳送。在使用Application Kit的應用程式中,當應用程式不作用時(not active),NSApplication物件自動會暫停通知傳遞。

注意,給註冊為NSNotificationSuspensionBehaviorDeliverImmediately的觀察者的通知,當它傳遞時會自動刷新隊列,導致所有那時排列好的通知也同時被傳遞。

暫停狀態可以被通知的貼出者(poster)覆寫。若通知是緊急的,像是server要關閉(shut down)的警告,貼出者可以藉由將NSDistributedNotificationCenter的postNotificationName:object:userInfo:deliverImmediately:方法的deliverImmediately引數設定成YES來貼出通知迫使通知立即被傳遞給所有的觀察者。

Unregistering an Observer

於正在觀察通知的物件被釋放前,必須告訴通知中心停止傳送通知給它。否則下一個通知會被送到不存在的物件並且程式會崩壞。你可以送出下面的訊息來完全移除做為局部通知(local notification)觀察者的物件,不論有多少物件和它所註冊的通知(應指不管這個物件註冊了多少份想要收到的通知)(原文:regardless of how many objects and notifications for which it registered itself):

 [[NSNotificationCenter defaultCenter] removeObserver:self];
 
對distributed notifications的觀察者傳送:
 
[[NSDistributedNotificationCenter defaultCenter] removeObserver:self];
 
使用較有明確指明通知名稱和觀察物件的removeObserver...方法去選擇性的取消註冊有特定通知的物件(selectively unregister an object for particular notifications)。

留言