前言:IOS的觀察者模式在IOS的使用頻率並沒有代理方法那麼高,從tableView到textField,在大多數情況下,都采用的是定義代理和實現代理的方式來進行函數的回調。
而觀察者模式也只是在使用通知中心的時刻才能用到,難道是觀察者模式比不上代理模式?雖然說,觀察者模式在效率上不如代理模式,但是使用觀察者模式可以實現程序的解耦,並且在層次結構比較深的地方,使用觀察者也比層層代理更加方便。
----------------------------
接下來,我們就對觀察者模式進行介紹:
觀察者模式:
觀察者模式,定義了在一對多的情況下的方法回調方式,一般來說,觀察者模式用於解除一個對象和多個對象間的耦合,分別是觀察者和被觀察者。被觀察者與觀察者間耦合程度降低,不管是有多少個監聽者,都不需要改變被監聽者的代碼。
基本過程是:
觀察者注冊成為被觀察者的監聽者,當被觀察者發生某些變化的時刻,就會觸發這個監聽,調用觀察者中的監聽方法。被觀察者通常通過一個容器來存儲監聽者,當自身發生某些變化的時刻,就會通知這個容器中的所有監聽者。
---------------------------
IOS中觀察者模式的實現:
觀察者模式的的思想非常簡單,Subject(主題)允許別的對象——觀察者(這些對象實現了觀察者接口)對這個Subject的改變進行訂閱和取消訂閱。當Subject發生了變化——那麼Subject會將這個變化發送給所有的觀察者,觀察者就能對Subject的變化做出更新。在這裡,Subject是報紙的出版社,而觀察者則是訂閱報紙的我和你,當Subject發生變化——有新的報紙,會做出通知——將報紙發送給所有的訂閱者。
什麼時刻使用觀察者模式:
當你需要將改變通知所有的對象時,而你又不知道這些對象的具體類型,此時就可以使用觀察者模式。
改變發生在同一個對象中,並在別的地方需要將相關的狀態進行更新
IOS中觀察者模式的實現方式:
在iOS中觀察者模式的實現有三種方法:Notification、KVO以及標准方法。
1.Notification(使用系統提供的通知中心)
NotificationCenter機制使用了操作系統的功能。通過NSNotificationCenter可以讓對象之間進行進行通訊,這些對象相互間可以不認識。當你用一個並行的流來推送通知,或者刷新數據庫,並希望在界面中能夠看到時,這非常有用。(我們對系統某些事件的監聽的時刻就可以使用這個方法,例如鍵盤抬起落下操作,某個textfield失去第一響應者的時刻,都會發送一個通知給通知中心,通過監聽這些通知,我們就可以與系統交互)
1.NSNotification * broadcastMessage = [ NSNotification notificationWithName: AnyNotification object: Self ];
2.NSNotificationCenter * notificationCenter = [ NSNotificationCenter defaultCenter];
3.[NotificationCenter postNotification: broadCastMessage];
上面的代碼中,創建了一個NSNotification類型的對象,並指定名稱為”broadcastMessage”,然後通過notificationCenter來發布這個消息。
要訂閱感興趣的對象中的相關事件,可以按照如下方法進行:
1.NSNotificationCenter * notificationCenter = [ NSNotificationCenter defaultCenter];
2.[NotificationCenter addObserver: Self selector: @ selector (update:) name: AnyNotification object: nil ];
2.KVO
鍵值觀察者:通過這種方式,某個對象的某個屬性發生變化的時刻,那些注冊的監聽者就會收到一個通知。
例如:我們要對某一個UIlabel的text進行監聽。當text變化的時刻就觸發某個方法。UIlabel* label;
KVO使用的NSObject自帶的
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
方法,這個方法會在這個對象監聽到通知的時刻調用。
--------
也就是說,我們可以通過覆寫繼承自NSObject的任何子類實現對通知的監聽。注意,是任何通知,在這個方法中需要通過判斷來區分不同的通知。
從這裡我們知道:其實任何繼承自Object的類都是能夠監聽通知的,所以,任何對象都可以被addObsever到某個被監聽的對象中去,然後在這個對象的observeValueForKeyPath中進行後續操作。
3:手動通知:
在上面的方法中,依賴的是系統給我們定義的自動通知,當某個屬性發生變化的時刻,系統就會自動發送通知給監聽者,而如果我們需要進一步定義通知發送時間的時刻,就應該使用手動發送通知的方式。
willChangeValueForKey:
didChangeValueForKey:這兩個方法就會發送指定key的通知。 4:自動通知:
[self setValue:[NSNumber numberWithBool:YES]forKey:@"isFinished"];
將觀察者與被觀察者注冊好之後,就可以對觀察者對象的屬性進行操作,這些變更操作就會被通知給觀察者對象。注意,只有遵循 KVO 方式來設置屬性,觀察者對象才會獲取通知,也就是說遵循使用屬性的 setter 方法,或通過 key-path 來設置:
自動通知是可以關閉的,automaticallyNotifiesObserversForKey方法就是用來設定某些key值自動通知,默認是所有的屬性都自動通知,通過設置某個key返回no關閉它的自動通知。在使用手動通知的時刻,一般就會關閉自動通知。