KVO和KVC常见问题:
1.KVC和KVO是什么.
2.KVC和KVO的原理是什么
3.KVC和KVO的使用场景
4.KVC和KVO的使用注意点
KVC
KVC,key-value-coding,键值编码
可以通过对某个属性,以字符串的形式,作为key,对这个key值设置value。
在一个类里面创建属性,系统会给当前的类创建带下划线的成员变量,所以只要知道了属性名称,就可以通过KVC对类的属性进行赋值。
@interface JCPerson : NSObject
@property(nonatomic, strong) NSString *age;
@end
@implementation JCPerson {
NSString *_name;
}
- (void)info {
NSLog(@"name: %@, age: %@",_name,_age);
}
@end
JCPerson *jcP = [[JCPerson alloc] init];
[jcP setValue:@"18" forKey:@"age"];
[jcP info];
[jcP setValue:@"19" forKey:@"_age"];
[jcP info];
[jcP setValue:@"lg" forKey:@"name"];
[jcP info];
[jcP setValue:@"lg" forKey:@"_name"];
[jcP info];
打印结果
name: (null), age: 18
name: (null), age: 19
name: lg, age: 19
name: lg2, age: 19
KVO
KVO的实现原理
- kvo基于runtime机制实现
- 使用了isa混写,当一个对象(假设是person对象,person的类是JCPerson)的属性值(假设person的age)发生改变时,系统会自动生成一个类,继承自JCPerson :NSKVONotifying_JCPerson,在这个类的setAge方法里面,调用
- [super setAge:age]
- [self willChangeValueForKey:@"age"]
- [self didChangeValueForKey:@"age"]
而这两个(2,3)方法内部会主动调用监听内部的-(void)observeValueForKeyPath这个方法,
- 想要看到NSKVONotifying_JVPerson很简单,在self.persong.age = 20;这里打断点,在调试区域就能看到person->NSObject->isa=(Class)NSNotifying JCPerson.
- 同时我们再self.person = [[JCPerson alloc]init];后打断点,看到-person->NSObject->isa=(Class)JCPerson,由此可见没在添加监听者之后,person类型已经由MYPerson被改变为NSKVONotifying_JCPerson.
- 因为我们在JCPerson类中对属性添加了addObserve。在值发生改变的时候,会在JCPerson类中实现了监听到属性值的变化。
KVO和KVC的使用场景
- KVO常见的使用场景在于Model和view的双向绑定
- KVC常见的使用场景在于修改系统类的属性值。
优缺点
- KVO使用完毕之后,添加完监听以后一定要注意移除
- 使用了KVO的地方,在以后代码的重构时候,注意要同步的修改,否则就会出现KVO的代码不再可用
- KVC修改了某个键值的时候,稳健点需要做一下版本适配,防止版本更新了之后,当前的key值发生了变化导致程序崩溃。