KVC与KVO
2015-07-15 07:21
232 查看
KVC与KVO
一:KVC(自定义一个Person类和Dog类,Persor类拥有name,money,和Dog对象属性,Dog拥有name和price属性)1.通过KVC获取值
获取单个词
Person *p = [Person new]; p.name = @"lmj"; p.money = 998; p.dog = [Dog new]; p.dog.name = @"wangcai"; p.dog.price = 110; NSLog(@"%@ , %f", p.name, p.money); NSString *name = [p valueForKey:@"name"]; NSLog(@"name = %@", name); double money = [[p valueForKey:@"money"] doubleValue]; NSLog(@"money = %f", money);
获取多层词
获取间接属性
// NSString *dogName = [p valueForKey:@"dog.name"]; // NSString *dogName = [p valueForKeyPath:@"dog.name"]; // NSLog(@"dogName = %@", dogName);
模型转字典
// NSDictionary *dict = [p dictionaryWithValuesForKeys:@[@"name", @"money"]]; // NSLog(@"%@", dict);
获取数组中对象的值
Person *p1 = [Person new]; p1.name = @"zs"; p1.money = 111; Person *p2 = [Person new]; p2.name = @"ls"; p2.money = 222; Person *p3 = [Person new]; p3.name = @"ww"; p3.money = 666; NSArray *arr = @[p1, p2, p3]; // 如果数组中的元素都是同一种类型的数据, 可以使用KVC获取数组中所有对象的某个属性的值 NSArray *res = [arr valueForKeyPath:@"name"]; NSLog(@"res = %@", res);
运算符:可以获取数组中的最大值,最小值,平均值
id res1 = [arr valueForKeyPath:@"@avg.money"]; NSLog(@"res = %@", res1);
2.通过KVC赋值
给属性赋单个词
// KVC == KEY VALUE CODING // Value : 值, 只能传对象 // forKey: 需要给谁(哪个属性)赋值 // setValue:forKey:方法, 只能给对象的直接属性赋值 [p setValue:@"lmj" forKey:@"name"]; // @(998.0) == [NSNumber numberWithDouble:(double)] [p setValue:@(668.0) forKey:@"money"];
多层赋值
// p.dog.name == [[p dog] setName:] // p.dog.name = @"wangwang"; // p.dog.price = 110.0; setValue:forKeyPath: 可以给对象的间接属性赋值. 多层赋值 // 建议: 以后在开发中都使用setValue:forKeyPath: // [p setValue:@"xiaoqiang" forKeyPath:@"dog.name"]; // [p setValue:@(110) forKeyPath:@"dog.price"]; #pragma mark 给私有成员变量赋值 /* // [p setValue:@"lnj" forKey:@"_name"]; // [p setValue:@(30) forKey:@"_age"]; // SEL sel = @selector(say); // [p performSelector:sel]; // [p say]; */
pragma mark 字典转模型
NSDictionary *dict = @{ @"name":@"xxx", @"money": @(998.1), // @"score":@(100) @"dog":@{ @"name":@"wangcai", @"price":@(110) } }; // p.name = dict[@"name"]; // p.money = [dict[@"money"] doubleValue];
注意点:
如果想使用KVC进行字典转模型, 那么字典中的key必须和模型中的属性一模一样(个数 + 名称),不然会报一个经典错误
this class is not key value coding-compliant for the key score.
如果使用KVC进行字典转模型, 只能对当前调用KVC方法的对象进行转换, 不能对它的属性的对象进行转换
setValuesForKeysWithDictionary:方法内部的实现原理
会拿到字典中的key, 然后根据这个key取出字典中的值, 然后再根据这个key赋值给对象
[p setValue:@"xxx" forKey:@"name"]; [p setValuesForKeysWithDictionary:dict];
二:KVO
// KVO == Key Value Observing // 作用: 可以监听某个对象属性的改变 Person *p = [Person new]; p.name = @"lnj"; p.age = 30; /* 第一个参数: 告诉系统哪个对象监听 第二个参数: 监听当前对象的哪个属性 第三个参数: 监听到属性改变之后, 传递什么值 第四个参数: 需要传递的参数 (这个参数不是传递给属性的) */ // 给p这个对象添加一个监听 , 监听p对象的age属性的改变, 只要age属性改变就通知self [p addObserver:self forKeyPath:@"age" options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew context:nil]; p.age = 50; NSLog(@"-------------------"); //p.age = 100; // 注意: 如果使用KVO监听某个对象的属性, 当对象释放之前一定要移除监听 // reason: 'An instance 0x7f9483516610 of class Person was deallocated while key value observers were still registered with it. // 注意: KVO只能监听通过set方法修改的值 /* KVO的原理: 只要给一个对象注册一个监听, 那么在运行时, 系统就会自动给该对象生成一个子类对象, 并且重写自动生成的子类对象的被监听属性的set方法, 然后在set方法中通知监听者 内部实现原理:会再setter方法中实现两个方法 - (void)setName:(NSString *)name { [self willChangeValueForKey:@"name"]; _name = name; [self didChangeValueForKey:name]; } NSKVONotifying_Person */ p->_age = 998;// (不能监听没有实现setter方法的属性) // 从p对象上移除self对它的age属性的监听 [p removeObserver:self forKeyPath:@"age"]; // (一定要在对象释放前移除,不然运行会报错) } // 只要监听到属性的改变就会调用 // keyPath: 被监听的属性名称 // object : 被监听的对象 // context: 注册监听的时候传入的值 - (void)observeValueForKeyPath:(nullable NSString *)keyPath ofObject:(nullable id)object change:(nullable NSDictionary *)change context:(nullable void *)context { NSLog(@"keyPath = %@, object = %@ , change = %@, context = %@", keyPath, object, change, context); }
相关文章推荐
- 马上着手开发 iOS 应用程序 至 读后笔记
- kvc简单介绍
- TableView的基本使用
- iOS KVC & KVO
- IOS 如何选择delegate、notification、KVO?
- KVO初体验
- IOS观察者模式之KVO代码
- kvo浅析与实例
- iOS KVO(键-值观察) 的使用总结
- KVC
- KVC 与 KVO 理解
- iOS-KVC究竟怎么用
- iOS-KVO究竟怎么用
- iOS开发-kvc
- Cocoa中KVO的简单用法【思路清晰】
- setValuesForKeysWithDictionary
- KVO/KVC
- 键值监听KVO
- KVC setvalue:forkey与setvalue:forkeypath的区别
- iOS-KVO