詳解Cocoa中監(jiān)聽、觀察和通知五種方法
Cocoa中監(jiān)聽、觀察和通知五種方法是本文要介紹的內(nèi)容,本文介紹Objective C中實現(xiàn)觀察者模式(也被稱為廣播者/監(jiān)聽者、發(fā)布/注冊或者通知)的五種方法以及每種方法的價值所在。該文章將包括:
1、手動廣播者和監(jiān)聽者(Broadcaster and listeners)
2、鍵-值觀察(Key Value Observing)
3、通知中心(Notification center)
4、上下文通知(Context notification)
5、用于觀察的委托(Delegate)
關于觀察者
觀察者模式是維持兩個模塊之間抽象關系的***大的方式之一。觀察者模式包括一個發(fā)布已發(fā)生事件的模塊以及響應該事件的另一模塊的若干個的實例。它和直接調(diào)用第二個模塊的方法不同,因為***個模塊不需要關注有多少個觀察者,從而實現(xiàn)觀察者和被觀察者之間更加完全的抽象關系。
手動廣播者和監(jiān)聽者
手動的方式需要廣播者保有一個監(jiān)聽者的數(shù)組(NSArray)或集合(NSSet)。在需要通知監(jiān)聽者一個事件的合適時機廣播者直接調(diào)用各個監(jiān)聽者上相關方法。
在廣播者類上你可能需要一個NSMutableArray、NSSet或NSMutableDictionary。NSMutableDictionary比較適合將事件標識符的類型作為每個監(jiān)聽者的鍵值。在廣播者上你還需要有監(jiān)聽者注冊和取消注冊的方法。
給NSArray或NSSet中的每個對象方式消息的方法很簡單,如下:
- [listenersCollection makeObjectsPerformSelector:@selector(methodSupportedByEveryListener)];
更多信息參見: Collections Programming Topics for Cocoa
優(yōu)點: 廣播者對監(jiān)聽者列表有完全的控制。
缺點: 在集合中手動添加或移除監(jiān)聽者(尤其是在由于其他原因已經(jīng)不被維護的情況下)。如果需要發(fā)布不同消息的情況下就需要更多的手動工作。
鍵值觀察
鍵值觀察協(xié)議時朝著自動化如上過程方向的一個很大進步。在很多情況下,廣播者不需要做任何事情。
每個Cocoa對象自動處理用于發(fā)布任何對象的addObserver:forKeyPath:options:context:。如果廣播者的“setter”方法遵循某些規(guī)則,“setter”方法就會自動觸發(fā)任何監(jiān)聽者的observeValueForKeyPath:ofObject:change:context:方法。
例如如下代碼就會在“source”對象上加入一個觀察者::
- [source addObserver:destination
- forKeyPath:@"myValue" options:NSKeyValueChangeNewKey
- context:nil];
這樣在每次調(diào)用setMyValue:方法的時候都會發(fā)送一個observeValueForKeyPath:ofObject:change:context:消息到destination。
你所需要做的就是在被觀察對象上注冊監(jiān)聽者并讓監(jiān)聽者實現(xiàn)
- observeValueForKeyPath:ofObject:change:context:
更多信息參見:NSKeyValueObserving Protocol Reference
優(yōu)點: 內(nèi)置的而且是自動的。可以觀察任何鍵路徑。支持依賴通知。
缺點: 廣播者無法知道誰在監(jiān)聽。方法必須符合命名規(guī)則以實現(xiàn)自動觀察消息的運作。監(jiān)聽者必須在被刪除之前被移除,否者接下來的通知就會導致崩潰和失效-不過這對于該文中指出的所有方法都是一樣的。
通知中心
NSNotificationCenter提供了一種更加解耦的方式。最典型的應用就是任何對象對可以發(fā)送通知到中心,同時任何對象可以監(jiān)聽中心的通知。
發(fā)送通知的代碼如下:
- [[NSNotificationCenter defaultCenter]
- postNotificationName:@"myNotificationName" object:broadcasterObject];
注冊接收通知的代碼如下:
- [[NSNotificationCenter defaultCenter] addObserver:listenerObject
- selector:@selector(receivingMethodOnListener:) name:@"myNotificationName" object:nil];
注冊通知的時候可以指定一個具體的廣播者對象,但這不是必須的。你可能注意到了defaultCenter 。實際上這是你在應用中會使用到的唯一的中心。通知會向整個應用開放,因此只有一個中心。
同時還有一個NSDistributedNotificationCenter。這是用來應用間通信的。在整個計算機上只有一個該類型的中心。
更多信息請參見:Notification Programming Topics for Cocoa
優(yōu)點: 通知的發(fā)送者和接受者都不需要知道對方??梢灾付ń邮胀ㄖ木唧w方法。通知名可以是任何字符串。
缺點: 較鍵值觀察需要多點代碼。在刪掉前必須移除監(jiān)聽者。
上下文通知
如果被觀察屬性是一個NSManagedOjbect的聲明屬性,就可以監(jiān)聽
- NSManagedObjectContextObjectsDidChangeNotification
這仍然使用NSNotification方式不過有點不同,因為NSManagedObject不會手動發(fā)送通知。
這種方法的注冊如下
- [[NSNotificationCenter defaultCenter]
- addObserver:listenerObejct selector:@selector(receivingMethodOnListener:)
- name:NSManagedObjectContextObjectsDidChangeNotification
- object:observedManagedObjectContext];
在receivingMethodOnListener:中,通知的userinfo中NSInsertedObjectsKey、NSUpdatedObjectsKey和NSDeletedObjectsKey等鍵值會給出受影響的對象集合。
更多信息請參見NSManagedObjectContext Class Reference
優(yōu)點: 是在整個NSManagedObjectContext中跟蹤變化的最簡單的方式。
缺點: 僅適用于Core Data并不能提供影響對象之外的具體信息。用于觀察的委托
***一個Cocoa簡化的觀察者模式是委托。廣義上說委托可以不僅僅處理簡單的觀察,但不一定需要做更多。 比如,NSApplication和NSWindow所有的通知都會同時傳給委托并由其處理。有些類會傳給它們的委托類似通知的消息,而不同時發(fā)送通知。比如NSMenu,發(fā)送menuWillOpen:給其委托但不會發(fā)送相應的NSNotification。 為了連接一個委托,只需在支持委托的對象上調(diào)用如下代碼:
- [object setDelegate:delegateObject];
對象可以收到任何它想要的委托消息。
更多信息請參見:Cocoa Fundamentals Guide: Delegates and Data Sources
優(yōu)點: 支持它的類有詳盡和具體信息。
缺點: 該類必須支持委托。某一時間只能有一個委托連接到某一對象。
小結:詳解Cocoa中監(jiān)聽、觀察和通知五種方法的內(nèi)容介紹完了,希望通過本文的學習能對你有所幫助!