闲的没事干,回顾了下KVO、KVC,为了保存学习获得的东西,写了这博文。希望过往的朋友能用到。
次博文中的KVO是直接写在ViewController里面的,看起来比较简单易懂。
一、Key Value Observing
Key Value Observing, 顾名思义就是一种observer 模式用于监听property的变化,KVO跟NSNotification有很多相似的地方, 用addObserver:forKeyPath:options:context:去start observer, 用removeObserver:forKeyPath:context去stop observer, 回调就是observeValueForKeyPath:ofObject:change:context:。
咱们先看看代码是怎么写的吧。并且把它两种使用方式做一下对比。
1、新建一个继承与NSObject的类Product。
#import <Foundation/Foundation.h>
@interface Product : NSObject
{
NSString *object;//这个是用于KVO中的Key,当你设置的key在这里面找不到,就会崩
}
@property (nonatomic ,copy) NSString *name;
@property (nonatomic ,assign) float price;
@property (nonatomic ,copy) NSString *content;
@end
知识点 一:
KVO与常规赋值的对比:
KVO:
[product setValue:@"小明" forKey:@"name"];
常规赋值:
product.name = @"小明";
在我的项目中使用了两种方式:一种是直接使用字典来监测,还有一种是直接使用对象来监测,在此只说明对象来监测的。
核心代码如下:
/**
对象
*/
pl = [[ProductList alloc]init];
[pl.product setValue:@"水果" forKey:@"name"];
[pl.product setValue:@"10.1" forKey:@"price"];
[pl.product setValue:@"水果很甜,值得一吃" forKey:@"content"];
[pl setValue:pl.product forKey:@"object"];
[pl addObserver:self forKeyPath:@"object" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:NULL];
//for循环添加对象到数组中
for (int i = 0; i < 10; i ++) {
Product *p = [[Product alloc]init];
[p setValue:[NSString stringWithFormat:@"鞋子%d",i] forKey:@"name"];
[p setValue:@(10*i) forKey:@"price"];
[p setValue:[NSString stringWithFormat:@"%d质量不错,很好,也很适合",i] forKey:@"content"];
[zhuangbeiArr addObject:p];
}
定义三个label和一个button,用来显示效果,当触发Button时切换到下一个
[pl setValue:zhuangbeiArr[index] forKey:@"object"];
分别在三个Lable上显示:
/**
* 通过对象实现切换
*
* @return <#return value description#>
*/
if ([keyPath isEqualToString:@"object"]) {
Product *p = [pl valueForKey:@"object"];
label.text = [p valueForKey:@"name"];
label1.text = [NSString stringWithFormat:@"%@",[p valueForKey:@"price"]];
label2.text = [p valueForKey:@"content"];
}
当执行完后,别忘记移除
- (void)dealloc{
/**
* 移除KVO
*/
[pl removeObserver:self forKeyPath:@"object"];
[product removeObserver:self forKeyPath:@"dic"];
}
对于KVO来说,我们要做的只是简单update 我们的property数据,不需要像NSNotificationCenter那样关心是否有人在监听你的请求,如果没有人监听该怎么办, 所有addObserver, removeObserver, callback 都是想要监听的你的property的class做的事情。 曾经做个项目,用NSNotificationCenter post Notification在一个network callback里面,可是这时候因为最早的addObserver的class被释放了, 接着生成的addObserver的class, 就接受到了上一个observer该监听的事件,所以造成了错误,那时候的解决方案是为addObserve key做unique,不会2次addObserver 的key是相同的,但是有了KVO, 我们同样可以用KVO来完成,当addOberver的的object remove的时候,就不会有这样的callback被调用了。
KVO给我们提供了更少的代码,和比NSNotification好处,不需要修改被观察的class, 永远都是观察你的人做事情。 但是KVO也有些毛病, 1. 如果没有observer监听key path, removeObsever:forKeyPath:context: 这个key path, 就会crash, 不像NSNotificationCenter removeObserver。 2. 对代码你很难发现谁监听你的property的改动,查找起来比较麻烦。 3. 对于一个复杂和相关性很高的class,最好还是不要用KVO, 就用delegate 或者 notification的方式比较简洁。