#### KVO簡單介紹與實現
Key Value Observing, 顧名思義就是一種observer 模式用于監聽property的變化,KVO跟NSNotification有很多相似的地方, 用addObserver:forKeyPath:options:context:去start observer, 用removeObserver:forKeyPath:context去stop observer, 回調就是observeValueForKeyPath:ofObject:change:context:。
KVO 的實現也依賴于 Objective-C 強大的 Runtime 。
簡單概述下 KVO 的實現:
當你觀察一個對象時,一個新的類會動態被創建。這個類繼承自該對象的原本的類,并重寫了被觀察屬性的 setter 方法。自然,重寫的 setter 方法會負責在調用原 setter 方法之前和之后,通知所有觀察對象值的更改。最后把這個對象的 isa 指針 ( isa 指針告訴 Runtime 系統這個對象的類是什么 ) 指向這個新創建的子類,對象就神奇的變成了新創建的子類的實例。
原來,這個中間類,繼承自原本的那個類。不僅如此,Apple 還重寫了 -class 方法,企圖欺騙我們這個類沒有變,就是原本那個類。更具體的信息,去跑一下 Mike Ash 的那篇文章里的代碼就能明白,這里就不再重復。
下面是從另外一個博客搞過來的示例代碼:
~~~
@interface StockData : NSObject {
NSString * stockName;
float price;
}
@end
@implementation StockData
@end
- (void)viewDidLoad
{
[super viewDidLoad];
stockForKVO = [[StockData alloc] init];
[stockForKVO setValue:@"searph" forKey:@"stockName"];
[stockForKVO setValue:@"10.0" forKey:@"price"];
[stockForKVO addObserver:self forKeyPath:@"price" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:NULL];
myLabel = [[UILabel alloc]initWithFrame:CGRectMake(100, 100, 100, 30 )];
myLabel.textColor = [UIColor redColor];
myLabel.text = [stockForKVO valueForKey:@"price"];
[self.view addSubview:myLabel];
UIButton * b = [UIButton buttonWithType:UIButtonTypeRoundedRect];
b.frame = CGRectMake(0, 0, 100, 30);
[b addTarget:self action:@selector(buttonAction) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:b];
}
-(void) buttonAction
{
[stockForKVO setValue:@"20.0" forKey:@"price"];
}
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if([keyPath isEqualToString:@"price"])
{
myLabel.text = [stockForKVO valueForKey:@"price"];
}
}
- (void)dealloc
{
[stockForKVO removeObserver:self forKeyPath:@"price"];
}
~~~