Key-Value Coding: 键值编码 (KVC)

方法调用:

// 对象属性
// 类似: Person -> name
setValue: forKey:
// 对象的属性或者 属性的属性...... 可见它已经包含前者.
// 类似: Person -> car -> name
setValue: forKeyPath:

KVC运用了一个isa-swizzling技术. isa-swizzling就是类型混合指针机制, 将2个对象的isa指针互相调换, 就是俗称的黑魔法.

KVC主要通过isa-swizzling, 来实现其内部查找定位的. 默认的实现方法由NSOject提供

  isa指针, 如其名称所指,(就是is a kind of的意思), 指向分发表对象的类. 该分发表实际上包含了指向实现类中的方法的指针, 和其它数据。

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

[object setValue:@"" forKey:@"uid"];

就会被编译器处理成:
// 首先找到对应sel
SEL sel = sel_get_uid("setValue:forKey:");
// 根据object->isa找到sel对应的IMP实现指针
IMP method = objc_msg_lookup (object->isa,sel);
// 调用指针完成KVC赋值
method(object, sel, @"", @"uid");

KVC键值查找原理

setValue:forKey:搜索方式

、首先搜索setKey:方法.(key指成员变量名, 首字母大写)
、上面的setter方法没找到, 如果类方法accessInstanceVariablesDirectly返回YES. 那么按 _key, _isKey,key, iskey的顺序搜索成员名.(NSKeyValueCodingCatogery中实现的类方法, 默认实现为返回YES)
、如果没有找到成员变量, 调用setValue:forUnderfinedKey:

valueForKey:的搜索方式

、首先按getKey, key, isKey的顺序查找getter方法, 找到直接调用. 如果是BOOL、int等内建值类型, 会做NSNumber的转换.
、上面的getter没找到, 查找countOfKey, objectInKeyAtindex, KeyAtindexes格式的方法. 如果countOfKey和另外两个方法中的一个找到, 那么就会返回一个可以响应NSArray所有方法的代理集合的NSArray消息方法.
、还没找到, 查找countOfKey, enumeratorOfKey, memberOfKey格式的方法. 如果这三个方法都找到, 那么就返回一个可以响应NSSet所有方法的代理集合.
、还是没找到, 如果类方法accessInstanceVariablesDirectly返回YES. 那么按 _key, _isKey, key, iskey的顺序搜索成员名.
、再没找到, 调用valueForUndefinedKey.

Key-Value Observing 键值观察(KVO), KVO是观察者模式的一种应用

观察者思想:

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

方法调用

// 添加一个观察者
[self.object addObserver:self forKeyPath:@"uid" options:NSKeyValueObservingOptionOld|NSKeyValueObservingOptionNew context:nil]; // 观察者监听到之后回调方法
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context {
NSLog(@"keyPath: %@", keyPath);
NSLog(@"object: %@", object);
NSLog(@"change: %@", change);
NSLog(@"context: %@", context);
} // 移除观察者, 类在销毁前需要销毁
[self.object removeObserver:self forKeyPath:@"uid"];

由此可见, 只有当我们调用KVC去访问key值的时候KVO才会起作用. 所以肯定确定的是, KVO是基于KVC实现的,

系统实现KVO有以下几个步骤:

  • 当类A的对象第一次被观察的时候,系统会利用运行时动态创建与类A一样的NSKVONotifying_A派生类, 并且只有1个属性的get, set方法实现.
  • 在派生类NSKVONotifying_A中重写类A的setter方法,NSKVONotifying_A类在被重写的setter方法中实现通知机制。
  • 类NSKVONotifying_A重写会 class方法,将自己伪装成类A。类NSKVONotifying_A还会重写dealloc方法释放资源。
  • 系统将所有指向类A对象的isa指针指向类NSKVONotifying_A的对象。

下面就是在调用KVO过程中object对象的isa指针指向

在没有添加观察者之前 isa 指向的是Student类

在添加完观察者之后, isa指针指向了NSKVONotifying_Student类, 所以能肯定NSKVONotifying_Student 是后来被创建出来作为监听用的

KVC, KVO 实现原理的更多相关文章

  1. KVC, KVO实现原理剖析

    iPhone程序开发 KVO/KVC实现机理分析是本文要介绍的内容,不多说,直接进入话题.我们来看详细内容. Objective-C里面的Key-Value Observing (KVO)机制,非常不 ...

  2. KVC/KVO原理详解及编程指南

    一.简介 1.KVC简介 2.KVO简介 二.KVC相关技术 1.Key和Key Path 2.点语法和KVC 3.一对多关系(To-Many)中的集合访问器方法 4.键值验证(Key-Value V ...

  3. 【转】 KVC/KVO原理详解及编程指南

    原文地址:http://blog.csdn.net/wzzvictory/article/details/9674431 前言: 1.本文基本不讲KVC/KVO的用法,只结合网上的资料说说对这种技术的 ...

  4. 转:KVC/KVO原理详解及编程指南

      作者:wangzz 原文地址:http://blog.csdn.net/wzzvictory/article/details/9674431 转载请注明出处 如果觉得文章对你有所帮助,请通过留言或 ...

  5. KVC/KVO 本质

    KVO 的实现原理 KVO是关于runtime机制实现的 当某个类的对象属性第一次被观察时,系统就会在运行期动态地创建该类的一个派生类,在这个派生类中重写基类中任何被观察属性的setter方法.派生类 ...

  6. KVC&KVO&运行时

    运行时:要先了解程序运行的三个阶段 1.编译阶段:clang将OC代码转换成C++,查看运行机制调用的方法 2.链接阶段:与我们使用到得库文件进行链接 3.运行阶段:我们要谈的运行时主要针对这个阶段, ...

  7. iOS KVO的原理

    KVO(Key Value Observing),是观察者模式在Foundation中的实现.   KVO的原理   简而言之就是:   1.当一个object有观察者时,动态创建这个object的类 ...

  8. kvc/kvo复习

    kvc/kvo复习 1 小问题 '[<XMGPerson 0x7fb8a8f30220> setValue:forUndefinedKey:]: this XMGPerson * pers ...

  9. 阶段性总结⓵触摸事件&手势识别⓶Quartz2D绘图⓷CALayer图层⓸CAAnimation⓹UIDynamic UI动力学⓺KVC&KVO

    知识点复习   1. 触摸事件&手势识别   1> 4个触摸事件,针对视图的 2> 6个手势识别(除了用代码添加,也可以用Storyboard添加)   附加在某一个特定视图上的, ...

随机推荐

  1. 洛谷P3656 展翅翱翔之时 (はばたきのとき)(洛谷2017.3月赛round1 t4)

    题目背景 船が往くよミライへ旅立とう 船只启航 朝未来展开旅途 青い空笑ってる(なにがしたい?) 湛蓝天空露出微笑(想做些什么?) ヒカリになろうミライを照らしたい 化作光芒吧 想就此照亮未来 輝きは ...

  2. 【NOIP考试范围】

    ※号为可能考察的算法[历年有出现过,但概率小,但最好掌握] [本图片仅作参考] 梦想总是要有的,万一实现了呢?

  3. 后渗透提权辅助工具BeRoot详解

    0x00 工具介绍 前言 BeRoot是一个后期开发工具,用于检查常见的Windows的配置错误,以方便找到提高我们提权的方法.其二进制编译地址为: https://github.com/Alessa ...

  4. Linux下chkconfig命令详解--(启动或停止)和查询系统服务的运行级信息

    chkconfig命令主要用来更新(启动或停止)和查询系统服务的运行级信息.谨记chkconfig不是立即自动禁止或激活一个服务,它只是简单的改变了符号连接. 使用语法:chkconfig [--ad ...

  5. 代码收藏系列--php--加载sql文件并解析成数组

    php加载sql文件,解析成以分号分割的数组.(支持存储过程和函数提取,自动过滤注释) /** * 加载sql文件为分号分割的数组 * <br />支持存储过程和函数提取,自动过滤注释 * ...

  6. [ACM][2018南京预赛]Magical Girl Haze

    一.题面 样例输入: 15 6 11 2 21 3 42 4 33 4 13 5 64 5 2 样例输出: 3 二.思路 关键词:分层BFS 考试时觉得题干意思很清晰——求可将k条边赋值为0的最短路. ...

  7. 【期望】【P5081】Tweetuzki 爱取球

    Description Tweetuzki 有一个袋子,袋子中有 \(N\) 个无差别的球.Tweetuzki 每次随机取出一个球后放回.求取遍所有球的期望次数. 取遍是指,袋子中所有球都被取出来过至 ...

  8. Java--Inheritance constructor继承中的构造方法问题(一)

    Java规定,一个父类可以同时拥有多个子类,但一个子类只能有一个父类,即单重继承,允许多层继承,即子类还可以有自己的子类,在下一层继承关系中原先的子类就变成了父类,这样的继承关系就形成了继承树. 子类 ...

  9. Myeclipse下配置SVN报错问题 svn: E175002: java.lang.RuntimeException: Could not generate DH keypair,缺少subclipse插件的javaHL

    在myeclipse10.0下安装svn插件,出现了Could not generate DH keypair,这么一个错误. 看到了一篇博客说是svn接口选择问题,可是我myeclipse没有那个接 ...

  10. python 分享文件

    http://note.youdao.com/noteshare?id=1787e8bf3a71fca16005ece3e7fffb6c