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. 在洛谷3369 Treap模板题 中发现的Splay详解

    本题的Splay写法(无指针Splay超详细) 前言 首先来讲...终于调出来了55555...调了整整3天..... 看到大部分大佬都是用指针来实现的Splay.小的只是按照Splay的核心思想和原 ...

  2. [BZOJ3172]单词

    3172: [Tjoi2013]单词 Time Limit: 10 Sec  Memory Limit: 512 MB Description 某人读论文,一篇论文是由许多单词组成.但他发现一个单词会 ...

  3. 【BZOJ2151】种树(贪心)

    [BZOJ2151]种树(贪心) 题面 BZOJ 题解 如果没有相邻不能选的限制,那么这就是一道傻逼题. 只需要用一个堆维护一下就好了. 现在加上了相邻点的限制,那么我们就对于当前位置加入一个撤销操作 ...

  4. 机器学习算法的Python实现 (1):logistics回归 与 线性判别分析(LDA)

    先收藏............ 本文为笔者在学习周志华老师的机器学习教材后,写的课后习题的的编程题.之前放在答案的博文中,现在重新进行整理,将需要实现代码的部分单独拿出来,慢慢积累.希望能写一个机器学 ...

  5. js 判断图片是否加载完成(使用 onload 事件)

    我们在写 jquery 的时候一般都会写 $(document).ready,加载完成事件还有一个就是 onload onload 与 ready 的区别是: 1.ready 是 DOM 加载完成的事 ...

  6. openssl生成https证书、转换证书格式的各种相关操作

    第一步:生成 private key.csr等文件 我们可能需要输入以下信息(交互式): --- Country Name (2 letter code) [AU]:US State or Provi ...

  7. git untrack file

    git update-index should do what you want This will tell git you want to start ignoring the changes t ...

  8. spoj 694 705 不相同的子串的个数

    http://www.spoj.com/problems/SUBST1/ SUBST1 - New Distinct Substrings #suffix-array-8 Given a string ...

  9. linux中使用随机数

    (1)单纯使用rand重复调用n次,就会得到一个0-RAND_MAX之间的伪随机数,如果需要调整范围,可以得到随机数序列后再进行计算.(2)单纯使用rand来得到伪随机数序列有缺陷,每次执行程序得到的 ...

  10. jeecms上传文件限制导致413-Request Entity Too Large

    1:spring mvc 上传限制大小  配置是否允许在上传文件的大小 <bean id="multipartResolver" class="org.spring ...