KVC/KVO 本质
KVO 的实现原理
KVO是关于runtime机制实现的
当某个类的对象属性第一次被观察时,系统就会在运行期动态地创建该类的一个派生类,在这个派生类中重写基类中任何被观察属性的setter方法。派生类在被重写的setter方法内实现真正的通知机制
如果原类为Person,那么生成的派生类名为NSKVONotifying_Person
每个类对象中都有一个isa指针指向当前类,当一个类对象的第一次被观察,那么系统就会偷偷讲isa指针指向动态生成的派生类,从而在给被监控属性复制是执行的是派生类的setter方法
键值观察通知依赖于NSObject的两个方法:willChangeValueForKey:和didChangeValueForKey:,在一个被观察属性发生改变之前,willChangeValueForkey:和didChangeValueForKey:;在一个被观察属性发生改变之前,willChangeValueForKey:一定会被调用,这就会记录旧的值。而当改变发生后,didChangeValueForKey:会被调用,继而observeValueForKey:ofObject:change:context:也会被调用
举例伪代码_NSSet*ValueAndNotify
- (void)setAge:(int)age
{
_NSSetIntValueAndNotify();
}
// 伪代码
void _NSSetIntValueAndNotify()
{
[self willChangeValueForKey:@"age"];
[super setAge:age];
[self didChangeValueForKey:@"age"];
}
- (void)didChangeValueForKey:(NSString *)key
{
// 通知监听器,某某属性值发生了改变
[oberser observeValueForKeyPath:key ofObject:self change:nil context:nil];
}

KVC的实现原理
- KVC是Key Value Coding的简称。它是一种可以通过字符串的名字(key)来访问类属性的机制。而不是通过调用Setter、Getter方法访问。KVC的方法定义在Foundation/NSKeyValueCoding中。
KVC使用的基本方法:
- (void)setValue:(nullableid)value forKey:(NSString*)key;//通过Key来设值
- (void)setValue:(nullableid)value forKeyPath:(NSString*)keyPath;//通过KeyPath来设值
- (nullableid)valueForKey:(NSString*)key;//直接通过Key来取值
- (nullableid)valueForKeyPath:(NSString*)keyPath;//通过KeyPath来取值
KVC 赋值 setValue:forKey:
- setValue:forKey:将键字符串key所对应的属性的值设置为value。(按照setKey:、_setKey:顺序查找方法)如果没有找到Set方法的话,将调用方法setValue:ForUndefinedKey:。并抛出异常 NSUnknowKeyException
2. 若没有找到Set方法,会调用对象的类方法+ (BOOL)accessInstanceVariablesDirectly;此方法返回YES时(默认返回YES),会按照_key,_iskey,key,iskey的顺序搜索成员,然后赋值。
3. 若都没找到成员变量,将调用方法setValue:ForUndefinedKey:。并抛出异常 NSUnknowKeyException
KVC 取值值 valueForKey:
按先后顺序搜索getKey:、key、isKey、三个
方法,若某一个方法被实现,取到的即是方法返回的值,后面的方法不再运行。如果是BOOL或者Int等值类型, 会将其包装成一个NSNumber对象。若这三个方法都没有找到,则会调用+ (BOOL)accessInstanceVariablesDirectly方法判断是否允许取成员变量的值。若返回NO,直接调用- (nullable id)valueForUndefinedKey:(NSString *)key方法,并抛出异常 NSUnknowKeyException
若返回YES,会按先后顺序取_key、_isKey、 key、isKey
成员变量的值。调用- (nullable id)valueForUndefinedKey:(NSString *)key方法。
补充
- KVC提供属性值正确性验证的API,它可以用来检查set的值是否正确、为不正确的值做一个替换值或者拒绝设置新值并返回错误原因。
- - (BOOL)validateValue:(inout id __nullable * __nonnull)ioValue forKey:(NSString *)inKey error:(out NSError **)outError;
KVC中的异常.获取值时找不到key- (nullable id)valueForUndefinedKey:(NSString *)key;
设值时找不到key- (void)setValue:(nullable id)value forUndefinedKey:(NSString *)key;
给不能设置nil的属性设置了nil。
- 如果你在SetValue方法时面给Value传nil,则会调用这个方法
- (void)setNilValueForKey:(NSString *)key;
KVC/KVO 本质的更多相关文章
- KVC/KVO原理详解及编程指南
一.简介 1.KVC简介 2.KVO简介 二.KVC相关技术 1.Key和Key Path 2.点语法和KVC 3.一对多关系(To-Many)中的集合访问器方法 4.键值验证(Key-Value V ...
- 【转】 KVC/KVO原理详解及编程指南
原文地址:http://blog.csdn.net/wzzvictory/article/details/9674431 前言: 1.本文基本不讲KVC/KVO的用法,只结合网上的资料说说对这种技术的 ...
- 转:KVC/KVO原理详解及编程指南
作者:wangzz 原文地址:http://blog.csdn.net/wzzvictory/article/details/9674431 转载请注明出处 如果觉得文章对你有所帮助,请通过留言或 ...
- 阶段性总结⓵触摸事件&手势识别⓶Quartz2D绘图⓷CALayer图层⓸CAAnimation⓹UIDynamic UI动力学⓺KVC&KVO
知识点复习 1. 触摸事件&手势识别 1> 4个触摸事件,针对视图的 2> 6个手势识别(除了用代码添加,也可以用Storyboard添加) 附加在某一个特定视图上的, ...
- kvc/kvo复习
kvc/kvo复习 1 小问题 '[<XMGPerson 0x7fb8a8f30220> setValue:forUndefinedKey:]: this XMGPerson * pers ...
- IOS开发之KVC KVO KVB
KVC(Key Value Coding) KVO(Key Value Observing) KVB(Key Value Binding) KVO是Cocoa的一个重要机制,他提供了观察某一属性变化的 ...
- 04 KVC|KVO|Delegate|NSNotification区别
一. iOS 中KVC.KVO.NSNotification.delegate 在实际的编程中运用的非常多,掌握好他们的运行原理和使用场合对于我们程序的开发将会带来事办工倍的效果: 二. KVC ...
- QF——OC中的KVC,KVO
KVC: (Key Value Coding) 键值编码 所谓KVC,其实就是不通过set和get方法访问对象属性,而是通过属性名字符串动态的去读取属性.KVC其实也是OC反射机制的一种运用. 之所以 ...
- 【iOS 开发】Objective - C 面向对象 - 方法 | 成员变量 | 隐藏封装 | KVC | KVO | 初始化 | 多态
一. Objective-C 方法详解 1. 方法属性 (1) OC 方法传参机制 Object-C 方法传参机制 : OC 中得参数传递都是值传递, 传入参数的是参数的副本; -- 基本类型 (值传 ...
随机推荐
- vue全局配置
Vue.config 是一个对象,包含Vue的全局配置.可以在启动应用之前修改下列的属性: Vue.config.slient=true; 取消Vue所有的日志与警告 默认值false ...
- zabbix snmp、jmx配置使用
SNMP: snmp是很古老的监控,我萌几乎可以在所有设备上看到它的身影 [root@linux-node1 ~]# yum install net-snmp net-snmp-libs net-sn ...
- 五、hibernate在myeclipse中生成实体和映射
- CF-798A
A. Mike and palindrome time limit per test 2 seconds memory limit per test 256 megabytes input stand ...
- python之log日志模块
logging的配置大致有下面几种方式. 1. 通过代码进行完整配置,logging.getLogger()获取logger后,给logger设置各种handler. 2. ...
- tcp/ip详解(转)
与UDP不同的是,TCP提供了一种面向连接的.可靠的字节流服务.TCP协议的可靠性主要有以下几点保障: (1)应用数据分割成TCP认为最适合发送的数据块.这部分是通过“MSS”(最大数据包长度)选项来 ...
- 保持plsql窗口布局
在window菜单中有个 save layout 项,设置好窗口布局后,选一下此项就保存你当前的窗口布局了,下次启动就不用再设置了.
- android摄像头获取图像——第一弹
http://www.cnblogs.com/mengyan/archive/2012/09/01/2666636.html 安卓读取视频的几种方式: 详细讲述请参考网址:http://www.cnb ...
- 我被面试官给虐懵了,竟然是因为我不懂Spring中的@Configuration
现在大部分的Spring项目都采用了基于注解的配置,采用了@Configuration 替换标签的做法.一行简单的注解就可以解决很多事情.但是,其实每一个注解背后都有很多值得学习和思考的内容.这些思考 ...
- Node.js 内置模块fs(文件系统)
fs模块的三个常用方法 1.fs.readFile() -- 读文件 2.fs.writeFile() -- 写文件 3.fa.stat() -- 查看文件信息 fs模块不同于其它模块的地方是它有异步 ...