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