IOS KVO KVC

一.KVC 键值编码

@interface NSObject(NSKeyValueCoding)

1.主要几种方法

获得属性值的方法:

- (nullable id)valueForKey:(NSString *)key;
- (nullable id)valueForKeyPath:(NSString *)keyPath;
- (nullable id)valueForUndefinedKey:(NSString *)key;

设置属性值的方法:

- (void)setValue:(nullable id)value forKey:(NSString *)key;
- (void)setValue:(nullable id)value forKeyPath:(NSString *)keyPath;
- (void)setValue:(nullable id)value forUndefinedKey:(NSString *)key;

是否能访问成员变量:

+ (BOOL)accessInstanceVariablesDirectly {
    return YES;
}

2.KVC键值查找

设置值时setValue:forKey搜索方式
1、首先搜索setKey: _setKey:两个方法。(key指成员变量名,首字母大写)
2、上面的setter方法没找到,
  ·类方法accessInstanceVariablesDirectly返回YES,允许访问成员变量。按 _key,_isKey,key,iskey的顺序搜索成员变量名。
  ·类方法accessInstanceVariablesDirectly返回NO。
3、没有找到成员变量,调用setValue:forUnderfinedKey:
4、未实现,程序崩溃,报NSUnknownKeyException

流程图
未命名文件.jpg
取值时valueForKey:搜索方式
1、按getKey,key,isKey,_key的顺序查找getter方法,找到直接调用。
2、方法accessInstanceVariablesDirectly返回YES。按 ![![未命名文件 (1).jpg](https://upload-images.jianshu.io/upload_images/4857852-29faa35b9aa51570.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
](https://upload-images.jianshu.io/upload_images/4857852-514d32790a98dfb6.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

    方法accessInstanceVariablesDirectly返回NO。
5、调用valueForUndefinedKey。

流程图:


123.jpg

3.KVC实现分析

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

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

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

//会被编译器处理成

SEL sel = sel_get_uid(setValue:forKey);
IMP method = objc_msg_loopup(site->isa,sel);
method(site,sel,@"sitename",@"name");

每个类都有一张方法表,是一个hash表,值是函数指针IMP,SEL的名称就是查表时所用的键。
SEL数据类型:查找方法表时所用的键。定义成char*,实质上可以理解成int值。
IMP数据类型:他其实就是一个编译器内部实现时候的函数指针。当Objective-C编译器去处理实现一个方法的时候,就会指向一个IMP对象,这个对象是C语言表述的类型。

KVC的内部机制:
一个对象在调用setValue的时候进行了如下操作:

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

https://juejin.im/post/6844903657444474887

二.KVO

http://www.cnblogs.com/zy1987/p/4616764.html
键值观察Key-Value-Observer就是观察者模式。

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


当注册观察者时,系统生成一个A类的子类KVONotifi_A类,
在KVONotifi_A中重写setter方法,
willchangeValue 原方法 didchangeValue 通知改变
系统将所有指向类A对象的isa指针指向类KVONotifi_A的对象。

KVO同KVC一样,通过 isa-swizzling 技术来实现。当观察者被注册为一个对象的属性的观察对象的isa指针被修改,指向一个中间类,而不是在真实的类。其结果是,isa指针的值并不一定反映实例的实际类。

所以不能依靠isa指针来确定对象是否是一个类的成员。应该使用class方法来确定对象实例的类。

https://www.jianshu.com/p/badf5cac0130
https://www.jianshu.com/p/8f83f592a354
https://www.jianshu.com/p/37a92141077e

KVOController
http://www.cnblogs.com/zy1987/p/4616063.html

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容