先介绍几个关于Runtime System的概念:
(1) isa指针:当一个对象被创建时,内存布局中的第一个元素是指向类结构的指针,即isa。通过isa指针,一个对象可以访问它的类结构,进而访问继承的类结构。
(2) SEL数据类型:它是编译器运行Objective-C里的方法的环境参数。
(3) IMP数据类型:它其实就是一个编译器内部实现时候的函数指针。当Objective-C编译器去处理实现一个方法的时候,就会指向一个IMP对象,这个对象是C语言表述的类型(事实上,在Objective-C的编译器处理的时候,基本上都是C语言的。
KVC、KVO、KVB概念区别
通过名字看上去,这三种很相似,但是其并不一样,不过其作用也是相辅相成的。这些功能都由系统框架提供支持,使用也很方便。下面简单描述下:
KVC就是类似使用[myObj setValue:key:]的方式去设置/获取属性值的操作方式
KVB是用来绑定对象与观察者的
KVO是观察者模式的一个改进版本,如果通过KVB绑定后,就可以通过KVO来获取对象属性更改的通知。
KVO机制
KVO(即Key-Value Observe)是cocoa针对观察者模式进行的改进,它提供了可以观察一个对象属性的方法,从而收到相应通知。这有点类似与NSNotification,但是NSNotification需要发送一个NSNotification对象,相比之下,KVO机制则显得更加简单。
KVC实现分析
KVC运用了一个isa-swizzling技术。isa-swizzling就是类型混合指针机制。KVC主要通过isa-swizzling,来实现其内部查找定位的。isa指针指向维护分发表的对象的类。该分发表实际上包含了指向实现类中的方法的指针,和其它数据。
比如说如下的一行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");
如上,使用KVC在调用setValue:forKey:对象时,大概分成三个步骤:
1. 获取SEL对象
2. 通过sel对象和当前的isa指针,获取函数指针(IMP对象)
3. 通过C函数指针的调用方式,直接调用函数(此处省去了发送消息的开销)
KVB(Key-Value Binding)
绑定,即为对象的观察者与被观察者之间建立联系。
1. 为调用对象添加观察者
- (void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context;
函数说明:
observer-观察者对象
keyPath-对象的key,需要观察的属性
options-观察键值变化的几种可选方式
context-可以传NULL,如果非NULL,则在观察者回调函数中会收到一些数据
2. 观察者收到消息后的处理函数
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context;
函数说明:
keyPath-对象的key,需要观察的属性
object-发送通知的对象
change-包含变化之前与变化之后属性值的字典
context-被观察者对象传入的context
后续会介绍Runtime System,计划在此对KVO/KVC进行一些分析。
可能包括如下:
KVC属性查找逻辑
KVO与观察者
KVO与NSNotification
by yytong