KVO与KVC
2018-09-28 本文已影响5人
sajiner
KVO
-
定义:
Key-Value Observing 即键值监听,用于监听某个对象属性值的变化 -
本质:
1> 利用运行时动态生成一个子类,并让实例对象的isa指针指向这个子类
2> 当设置instance对象的属性时,会调用Foundation的_NSSet{XXX}ValueAndNotify函数,该函数内部实现如下:
a)调用willChangeValueForKey:
b)调用父类原来的setter
c)调用didChangeValueForKey:(didChangeValueForKey:内部会调用observer的observeValueForKeyPath:ofObject:change:context:方法) -
运行时生成的中间类NSKVONotifying_{ClassName}的内部组成
isa
superclass
setAge: (IMP指向_NSSet{XXX}ValueAndNotify的实现)
class
dealloc
_isKVOA
如何得知添加KVO的instance对象的isa指针指向的不是原有的类对象
- 在添加KVO之前和之后分别打印instance对象的isa指针
NSLog(@"person添加kvo之前 - %@", object_getClass(self.person)); /// Person
[self.person addObserver:self forKeyPath:@"age" options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew context:nil];
NSLog(@"添加kvo之后 - %@", object_getClass(self.person)); /// NSKVONotifying_Person
添加了KVO的instance对象和未添加KVO的对象同是调用属性的set方法,为什么添加KVO的可以触发 observeValueForKeyPath:ofObject:change:context:方法
- 猜想,是不是运行时生成的子类中的set方法实现不一样,代码如下
NSLog(@"person添加kvo之前 - %p", [self.person methodForSelector:@selector(setAge:)]); /// 0x10e3a0250
[self.person addObserver:self forKeyPath:@"age" options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew context:nil];
NSLog(@"person添加kvo之后 - %p", [self.person methodForSelector:@selector(setAge:)]); /// 0x10e7509e4
- 由上边的打印发现,set方法的IMP在添加KVO前后有变化
- 断点,在控制台输入命令 p (IMP)0x1084e19e4 ,得到如下信息,可知添加了KVO后,调用属性的set方法,会自动触发Foundation的_NSSetIntValueAndNotify方法,而_NSSetIntValueAndNotify方法内部实现了如下操作
a)调用willChangeValueForKey:
b)调用父类原来的setter
c)调用didChangeValueForKey:(didChangeValueForKey:内部会调用observer的observeValueForKeyPath:ofObject:change:context:方法)
(IMP) $1 = 0x00000001084e19e4 (Foundation`_NSSetIntValueAndNotify)
如何手动触发KVO
手动调用willChangeValueForKey:和didChangeValueForKey:方法
KVC
-
定义:
Key-Value Coding,即键值编码,可以通过某个key来访问属性 -
常见API;
-(void)setValue:(id)value forKeyPath:(NSString *)keyPath;
-(void)setValue:(id)value forKey:(NSString *)key;
-(id)valueForKeyPath:(NSString *)keyPath;
-(id)valueForKey:(NSString *)key; -
setValue:forKey:的原理
setValue的原理.png
-
valueForKey:的原理
valueForKey的原理.png