KVO和KVC的实现原理

Key-Value Coding(KVC)

KVC运用了一个isa-swizzling技术。isa-swizzling就是类型混合指针机制。KVC主要通过isa-swizzling,来实现其内部查找定位的。isa指针,如其名称所指,(就是is a kind of的意思),指向维护分发表的对象的类。该分发表实际上包含了指向实现类中的方法的指针,和其它数据

KVC是一种间接访问对象属性(用字符串表征)的机制,而不是直接调用对象的accessor方法或是直接访问成员对象。

比如说如下的一行KVC的代码:

[site setValue:@"sitename" forKey:@"name"];

就会被编译器处理成:

SEL sel = sel_get_uid ("setValue:forKey:");

IMP method = objc_msg_lookup (site->isa,sel);

method(site, sel, @"sitename", @"name");

关于上面的代码有一些方便理解的小注释

一个对象在调用setValue的时候,(1)首先根据方法名找到运行方法的时候所需要的环境参数。(2)他会从自己isa指针结合环境参数,找到具体的方法实现的接口。(3)再直接查找得来的具体的方法实现

Key-Value Observing(KVO)

一个目标对象管理所有依赖于它的观察者对象,并在它自身的状态改变时主动通知观察者对象。这个主动通知通常是通过调用各观察者对象所提供的接口方法来实现的。观察者模式较完美地将目标对象与观察者对象解耦。

当观察者为一个对象的属性进行了注册,被观察对象的isa指针被修改的时候,isa指针就会指向一个中间类,而不是真实的类。所以isa指针其实不需要指向实例对象真实的类。所以我们的程序最好不要依赖于isa指针。在调用类的方法的时候,最好要明确对象实例的类名。

因为KVC的实现机制,可以很容易看到某个KVC操作的Key,而后也很容易的跟观察者注册表中的Key进行匹对。假如访问的Key是被观察的Key,那么我们在内部就可以很容易的到观察者注册表中去找到观察者对象,而后给他发送消息。

但需要注意的是只有当我们调用KVC去访问key值的时候KVO才会起作用。所以肯定确定的是,KVO是基于KVC实现的

注册

[self.person  addObserver : self  forKeyPath : @"age"  options : NSKeyValueObservingOptionOld  | NSKeyValueObservingOptionNew  context : nil ];

只要当前类中 age 这个属性发生的变化都会触发到以下的方法

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary*)change context:(void *)context {

NSLog(@"%@", change);

}

同时不要忘记在 dealloc中移除监听

-( void )dealloc{

[ self . person  removeObserver : self  forKeyPath : @"age" ];

}


KVO和KVC的实现原理_第1张图片

当这个类第一次被监听时,系统会在运行时期动态地创建一个继承XqPersion的NSKVONOtifying_Persion类

KVO和KVC的实现原理_第2张图片

在这个派生类中,重写基类中任何被观察属性的setter方法,在setter方法中实现真正的通知机制.

你可能感兴趣的:(KVO和KVC的实现原理)