KVC与KVO
2018-02-27 本文已影响5人
ForzaJuven
一、KVC
KVC key-value-coding即键值编码,通常用于对某一个对象的属性进行赋值。且可以对私有属性进行赋值
基本用法如下
[Person setValue:@"张三" forKey:@"name"];
[Person setValue:@20 forKey:@"age"];
用此方法如果Person中有一个属性Dog,Dog又有自己的一个属性dogname,那么要对那么dogname进行赋值时[Person setValue:@"littleblack" forKey@"Dog.dogname"]
会报错。此时应该使用forKeyPath方法:
[Person setValue@"littleblack" forKeyPath:@"Dog.dogname"];
所以使用KVC时最好使用forKeyPath方法;
KVC除了访问私有变量这个用处外,还可以用于字典转模型.在person类对外提供一个接口,将转模型的工作放在模型中进行
- (instancetype)initWithDict:(NSDictionary *)dict
{
if (self = [super init]) {
//普通方法
//self.name = dict[@"name"];
//self.age = dict[@20];
//KVC 缺点:字典中的键值对必须与模型中的键值对完全对应,否则程序会崩溃
[self setValuesForKeysWithDictionary:dict];
}
returnself;
}
外面可以直接将字典传入,和平常转模型相比,kvc更加方便,减少了代码量。
NSDictionary*PersonDict = @{@"name":@"李四",@"age":@"18"};
Person *p2 = [Person personWithDict:PersonDict];
NSLog(@"name = %@,age =%ld",p2.name,p2.age);
总结:
1.KVC一般用于对私用变量进行取值和赋值
2.KVC还可用于字典转模型,但是无法处理复杂的字典,且字典中的键值对必须与模型中的键值对完全对应,否则程序会崩溃
二、KVO
KVO即key-value-observing,利用一个key来找到某个属性并监听其值的改变。其实这也是一种典型的观察者模式。
1.添加观察者
2.在观察者中实现监听方法observeValueForKeyPath: ofObject: change: context:
(通过查阅文档可以知道,绝大多数对象都有这个方法,因为这个方法属于NSObject)
3.移除观察者
具体代码:
/*
NSKeyValueObservingOptionNew =
0x01, 新值
NSKeyValueObservingOptionOld =
0x02, 旧值
*/
// 利用KVO监听p对象name 属性值的改变
Person *p = [[XMGPerson alloc] init];
p.name = @"jack";
/* 对象p添加一个观察者(监听器)
Observer:观察者(监听器)
KeyPath:属性名(需要监听哪个属性)
*/
[p addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:@"123"];
/**
* 利用KVO 监听到对象属性值改变后,就会调用这个方法
*
* @param keyPath 哪一个属性被改了
* @param object 哪一个对象的属性被改了
* @param change 改成什么样了
*/
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context
{
// NSKeyValueChangeNewKey == @"new"
NSString *new = change[NSKeyValueChangeNewKey];
// NSKeyValueChangeOldKey == @"old"
NSString *old = change[NSKeyValueChangeOldKey];
NSLog(@"%@-%@",new,old);
}
最后不要忘记,和通知一样,要在dealloc方法里面移除监听
- (void)dealloc
{
[a removeObserver:bforKeyPath:@"name"];
}