在一個複雜的,有狀態的系統中,當一個對象的狀態發生改變,如何通知系統,並對狀態改變作出相應的行爲是必需考慮的一個問題,在iOS中爲這類問題提供了4種解決方法:
1. NSNotifiactaion和NSNotificationCenter:通知中心
2. Delegates:代理,
3. Callback:回調,
4. KVO(Key-Value Observing):鍵值觀察
這篇文章就來講說經過KVO通知系統狀態發生改變的用法。
KVO是什麼?
KVO是Object-C中定義的一個通知機制,其定義了一種對象間監控對方狀態的改變,並作出反應的機制。對象能夠爲本身的屬性註冊觀察者,當這個屬性的值發生了改變,系統會對這些註冊的觀察者作出通知。其用途十分普遍,比方說,你的下載進度條是根據下載百分比決定的,那麼,能夠經過觀察下載百分比的改變,刷新進度條的樣式,來直觀的反應下載進度等等。
KVO的用法
根據上面的描述,一個KVO的用法主要就涉及3個部分:
1.爲對象的屬性註冊觀察者:對象經過調用下面這個方法爲屬性添加觀察者
html
- (void)addObserver:(NSObject *)observer spa
forKeyPath:(NSString *)keyPath 代理
options:(NSKeyValueObservingOptions)options server
context:(void *)context htm
observer: 觀察者對象. 其必須實現方法observeValueForKeyPath:ofObject:change:context:.對象
keyPath: 被觀察的屬性,其不能爲nil.blog
options: 設定通知觀察者時傳遞的屬性值,是傳改變前的呢,仍是改變後的,具體的設定能夠這兒:https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Protocols/NSKeyValueObserving_Protocol/Reference/Reference.html#//apple_ref/doc/c_ref/NSKeyValueObservingOptions,一般設置爲NSKeyValueObservingOptionNew。生命週期
context: 一些其餘的須要傳遞給觀察者的上下文信息,一般設置爲nil作用域
2.觀察者接收通知,並作出處理:觀察者經過實現下面的方法,完成對屬性改變的響應:
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context
keyPath: 被觀察的屬性,其不能爲nil.
object: 被觀察者的對象.
change: 屬性值,根據上面提到的Options設置,給出對應的屬性值
context: 上面傳遞的context對象。
3.清除觀察者:對象經過下面這個方法移除觀察者:
- (void)removeObserver:(NSObject *)anObserver forKeyPath:(NSString *)keyPath
4. 注意事項:
使用KVO消息傳遞機制有兩個要求:(1)觀察者必須知道被觀察對象,即在同一做用域。(2)觀察者還須要知道被觀察對象的生命週期,由於在銷燬發送者對象以前,須要取消觀察者的註冊。
另外:若是計劃在Core Data對象上使用KVO,須要知道這跟通常的KVO使用方法有點不一樣。還必須結合Core Data的故障機制(faulting mechanism),一旦core data出現了故障,它將會觸發其屬性對應的觀察者(即便這些屬性值沒有發生改變)。
5. 一些好的實踐
(1)當一個觀察者觀察多個對象的相同屬性(即不一樣Object,可是KeyPath相同),可經過設定靜態的Context變量來區分不一樣的通知。
(2)使用NSStringFromSelector(@selector(method))來獲取KeyPath,而不是直接經過NSString寫屬性名,這樣編譯器能夠幫助發現屬性名中的Typo。
(3)經過方法:+ (NSSet *)keyPathsForValuesAffectingValueForKey:(NSString *)key,經過一個Key觀察多個屬性值的改變。
參考文章:http://ningandjiao.iteye.com/blog/2009729