觀察者模式容許一個對象在它的狀態發生變化時通知多個觀察者,而被觀察的對象無需對觀察者有特定的認識。觀察者模式在cocoa中以多種形式出現,包括NSNotification、委託觀察遺蹟鍵-值觀察(kvo)。他促使對象之間產生弱藕合,以使組建更具可重用性而且更加健壯。app
大多數cocoa開發者都遇到過NSNotificationCenter ,它容許經過一個對象註冊被通知的事件來提供鬆散耦合,該事件被字符串名稱定義,通知比kvo更容易理解和實現,下面是關於如何使用它的多示例。異步
//Poster.h //爲通知定義一個字符串常量 //注意這樣是聲明一個指向不可變字符串的常量指針 extern NSString *const PosterDidSomethingNotificaton;
//Poster.m NSString *const PosterDidSomethingNotificaton=@"PosterDidSomethingNotificaton"; /* *... */ //其中的發送者做爲通知的對象 [[NSNotificationCenter defaultCenter] postNotificationName:PosterDidSomethingNotificaton object:nil];
Observe.m //導入Poster.h以獲取字符串常量 #import "Poster.h" //... //註冊以接收通知 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(PosterDidSomething:) name: PosterDidSomethingNotificaton object:nil]; ... -(void)PosterDidSomething{ //在這裏處理通知 } -(void)dealloc{ //老是在這裏移除你的觀察者 [[NSNotificationCenter defaultCenter] removeObserver:self]; [super dealloc]; }
觀察者應該考慮是否要觀察一個特定的對象活着nil(全部具備給定名稱的通知,與object的值無關。)post
屢次使用相同參數調用addObserver:selector:name:object: 方法會致使收到多個回調,但這些回調幾乎不是你想要的,通常來講最簡答方法是在init理開始觀察通知並在dealloc裏中止,但若是你想要查看來自某個屬性的通知,而這個屬性可變呢?下面的示例演示如何編寫setPoster:方法方便正確的爲poster屬性添加或者益處觀察者:線程
-(void)setPoster:(Poster *) aPoster{ NSNotificationCenter *nc=[NSNotificationCenter defaultCenter]; if(_poster!=nil){ //針對舊值益處全部觀察者 [nc removeOberver:self name:nil object:_poster]; } _poster=aPoster; if(_poster!=nil){ [nc addObserver:self selecter:@selecter(anEventDidHappen:) name:PosterDidSomethingNotification object:_poster]; } } //這裏設置nil很是重要,把nil做爲object或者name傳遞的意思是「任何對象/通知」。
要是你想觀察來自大量對象的某個通知但不必定每一個對象都會發生通知又改怎麼辦呢?好比你可能喜歡隨意切換歌曲,但僅限於當前播放列表裏的歌曲。你能夠一首首的聽,但這樣很是繁瑣,下面展現一種觀察nil而且檢查你真正想要毀掉的好方法。指針
//觀察全部對象,不管是否在你的曲目列表中 [[NSNotificationCenter defaultCenter] addOberver:self selector:@selector(trackaDidChange:) name:TrackDidChangeNotification object:nil]; //... -(void)trackaDidChange{ //確認這首歌曲不是你想聽的 if([self.tracks containsObject: [note object]]){ /* *... */ } }
這種方法下降了觀察的數量,但在回調過程當中添加了一個額外的檢查。code
發生通知時同步的,這可能會讓那些但願在另外一個線程上執行通知貨其餘方式異步運行通知的開發者感到不便,server