鍵-值觀察者(key - value observing)是指當指定的對象的屬性被修改時,允許對象接收通知的機制。
總的來說,也就是告訴一個對象,“我想要觀察你的fido屬性,如果它發生了變化,就通知我。當setFido: 方法被調用的時候,被觀察的對象會發送消息告訴你,我的fido屬性有一個新值了。”討論KVO和討論NSNotificationCenter時使用的語言很相似,二者底層實現原理很相似。
觀察、回調
- 添加觀察
- 無論lastTime何時發生變化,都要通知我它改變的新值以及改變之前的舊值
[被觀察者 addObserver: 觀察者
forKeyPath: @"被觀察者的某一屬性"
options: NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld
context: nil];
實現被觀察屬性發生變化時的回調方法
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)cahnge
context:(void *)context {
NSString *oldValue = [change objectForKey:NSKeyValueChangeOldKey];
NSString *newValue = [change objectForKey:NSKeyValueChangeNewKey];
}
- 在KVO中使用context
注意: 當在代碼中將某個對象注冊為觀察者時,你需要傳遞指針為context。當接收變化的通知時,context會隨通知一起發送。context可以用來回答:“這真的是我需要的通知嗎?”例:
static int contextForKVO;
[被觀察者 addObserver: self
forKeyPath: @"fido"
options:0
context: &contextForKVO];
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)cahnge
context:(void *)context {
// 這是不是我的?
if (context != &contextForKVO) {
// 將它傳遞給父類
[super observerValueForKeyPath:keyPath];
} else {
// 處理變化
}
}
- 顯式觸發通知
如果使用存取方法來設置屬性,那么系統就會自動通知觀察者。但由于某種原因,你選擇不適用存取方法呢?這時可以通過willChangeValueForKey:和didChangeValueKey:方法通知系統木某個屬性的值即將/已經發生變化。
NSDate *now = [NSDate date];
[self willChangeValueForKey:@"lastTime"];
_lastTime = now;
[self didChangeValueForKye:@"lastTime"];
- 獨立的屬性
如果你不想觀察_lastTime而想觀察_lastTimeString,可以通過一個類方法來做這項工作。
+ (NSSet *)keyPathsForValuesAffectingLastTimeString {
retutn [NSSet setWithObject:@"lastTime"];
}
注:摘自《Objective-C編程》(第2版)page 301