1.什么是KVC?KVO?
KVC:Key Value Coding (键值编码)
//Person.h文件
@property (nonatomic,copy) NSString *name;
@property (nonatomic,assign) int age;
//常规赋值
Person *p = [[Person alloc] init];
p.name = @"zs";
p.age = 18;
//KVC赋值
[p setValue:@"王五" forKey:@"name"];
[p setValue:@"19" forKeyPath:@"age"];
注意:
1.使用KVC可以进行自动类型转换
forKey和forKeyPath的区别:
//Person.h文件
@property (nonatomic,strong) Dog *dog;
//main文件
Person *p = [[Person alloc] init];
[p.dog setValue"ahsh" forKeyPath:@"name"];
[p.dog setValue:@"hsff" forKey:@"name"];
[p setValue:@"ahsjhf" forKeyPath:@"dog.name"];
总结:
(1)forKeyPath 包含了所有 forKey的功能
(2)forKeyPath 可以进行内部点语法,层层访问内部属性
注意:key值一定要在属性中找到
修改内部的私有的成员变量
//person.h
@implementation Person
int _age;
@end
Person *person = [[Person alloc] init];
[person setValue:20 forKey:@"_age"];
字典转模型
-(instancetype)initWithDict:(NSDictionary *)dict{
//[dict enumerateKeysAndObjectUsingBlock:^(id _Nullable key, id _Nullable value, BOOL _Nullable stop){
//[self setValue:value forKey:key];
//}]
等价于:
[self setValuesForKeysWithDictionary:dict];
//在开发中,不建议使用
//字典中的key值必须在模型的属性中找到,一一对应才可以
//如果模型中带有模型,这个方法不好使
//应用场景:简单的字典转模型
}
取值操作
WLYPerson *person = [[WLYPerson alloc] init];
[person valueForKeyPath:@"name"];
模型转字典
WLYPerson *person = [[WLYPerson alloc] init];
[person dictionaryWithValuesForKeys:@[@"name",@"money"]];
可以取出数组中所有对象的属性
Person *person1 = [[Person alloc] init];
Person *person2 = [[Person alloc] init];
Person *person3 = [[Person alloc] init];
Person *person4 = [[Person alloc] init];
NSArray *arr = @[person1, person2, person3, person4];
NSArray *allPersonNames = [arr valueForKeyPath:@"name"];
原理:
去模型中查找有没有对应的属性的set方法,有的话就把value传给set方法,调用赋值
找不到的话,去模型中查找有没有对应的属性,有的话直接访问属性赋值
去模型中查找有没有_source属性,有的话直接访问属性赋值
找不到,就会直接报错
KVO: Key Value Observing (键值监听)
当某个对象的某个属性值发生改变的时候(用KVO监听)
XMGPerson *person = [[XMGPerson alloc] init];
person.name = @"张三";
person.name = @"李四";
person.name = @"王五";
/*
作用:给对象绑定一个监听器(观察者)
-Observer:观察者
-KeyPath:要监听的属性
-options:选项,方便方法中拿到属性值
*/
[person addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew context:nil];
[person removeObserver:self forKeyPath:@"name"];
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id>)change context:(void *)context{
}