KVC
kvc提供了一种在运行时而非编译时动态访问对象属性与成员变量的方式,该方法不需要调用get/set方法
OC中访问变量的方式
- _name 直接访问
- self.name 利用属性访问
- [self setValue:@"" forKey:@""] KVC
[self valueForKey:@"someKey"];
查找过程:
1.查找对象是否带有someKey这个方法
2.查找对象是否代用someKey这个实例变量(iVar)
3.调用 -(id)valueForUndefinedKey
4.抛出NSUndefinedKeyException异常
KVC内部实现
一个对象在调用setValue时
1.根据方法名找到运行方法的时候所需要的环境参数
2.从自己的isa指针结合环境参数,找到具体的方法实现的接口,isa指针,指向维护分发表的对象的类,该分发表实际上包含了指向实现类中的方法的指针
3.直接查找得来的具体的方法实现
@interface LBKVC : NSObject {
NSString *firstName;
}
@property (nonatomic, strong) NSString *lastName;
@end
[_kvc setValue:@"dog" forKey:@"lastName"]; // 属性 会触发 set 方法
[_kvc setValue:@"cat" forKey:@"firstName"]; // 成员变量 没有set方法
KVO
KVO主要用来解耦
在上面介绍的KVC机制上加上KVO的自动观察消息通知机制就水到渠成了。
*KVO是基于runtime机制实现的
*当某个类的属性对象被观察时,系统会在运行期动态地创建该类的一个派生类,在这个派生类中重写基类中任何被观察属性的setter方法。派生类在被重写的setter方法内实现真正的通知机制
*如果原来类为Person,那么生成的派生类名为NSKVONotifying_Person
*每个类对象中都有一个isa指针指向当前类,当一个类对象被观察,那么系统会偷偷将isa指针指向动态生成的派生类,从而在给被监控属性赋值时执行的是派生类的setter方法
*键值观察通知 依赖于NSObject的两个方法 willChangeValueForKey 和 didChangeValueForKey 。在一个被观察属性发生改变之前,willChangeValueForKey 一定会被调用,这样就会记录旧的值,而当值改变后,didChangeValueForKey 会被调用,继而observeValueForKey:ofObject:change:context:也会被调用
// 手动触发
[self willChangeValueForKey:@"name"];
[self didChangeValueForKey:@"name"];
网友评论