IOS 开发中的KVC 和KVO,实践。
KVO
即key-value-observing,利用一个key来找到某个属性并监听其值得改变。其实这也是一种典型的观察者模式。
1,添加观察者
2,在观察者中实现监听方法,observeValueForKeyPath: ofObject: change: context:
3,移除观察者
interface WebviewViewController ()
@property (nonatomic, strong) WKWebView *webView;
@property (nonatomic, strong) UIProgressView *progressView;
@end
// 让对象 self 监听对象 self.webView 的estimatedProgress属性
// options属性可以选择是哪个 /* NSKeyValueObservingOptionNew =0x01, 新值 NSKeyValueObservingOptionOld =0x02, 旧值 */
// context 带参数(字典等)
[self.webView addObserver:self
forKeyPath:@"estimatedProgress"
options:NSKeyValueObservingOptionNew
context:nil];
#pragma mark- KVO监听
/*
* 当对象的属性发生改变会调用该方法
*@param keyPath 监听的属性
* @param object 监听的对象
* @param change 新值和旧值
* @param context 额外的数据
*/
- (void)observeValueForKeyPath:(NSString*)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void*)context
{
if ([keyPath isEqualToString:@"estimatedProgress"]) {
self.progressView.progress = self.webView.estimatedProgress;
// 加载完成
if(self.webView.estimatedProgress >=1.0f) {
[UIView animateWithDuration:0.25f animations:^{
self.progressView.alpha=0.0f;
self.progressView.progress=0.0f;
}];
}else{
self.progressView.alpha=1.0f;
}
}
}
- (void)dealloc {
[self.webView removeObserver:self forKeyPath:@"estimatedProgress" context:nil];
}
KVO是利用runtime动态添加了子类,当一个类的属性被观察的时候,系统会通过runtime动态的创建一个该类的派生类,并且会在这个类中重写基类被观察的属性的setter方法,而且系统将这个类的isa指针指向了派生类,从而实现了给监听的属性赋值时调用的是派生类的setter方法。重写的setter方法会在调用原setter方法前后,通知观察对象值得改变。
调用willChangeValueForKey:和didChangevlueForKey:,最后调用observeValueForKey:ofObject:change:context:方法,是通过上两个方法来记录新值和旧值的。