KVO 的实现原理

  1. KVO是关于runtime机制实现的

  2. 当某个类的对象属性第一次被观察时,系统就会在运行期动态地创建该类的一个派生类,在这个派生类中重写基类中任何被观察属性的setter方法。派生类在被重写的setter方法内实现真正的通知机制

  3. 如果原类为Person,那么生成的派生类名为NSKVONotifying_Person

  4. 每个类对象中都有一个isa指针指向当前类,当一个类对象的第一次被观察,那么系统就会偷偷讲isa指针指向动态生成的派生类,从而在给被监控属性复制是执行的是派生类的setter方法

  5. 键值观察通知依赖于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:

  1. 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:

  1. 按先后顺序搜索getKey:、key、isKey、三个方法,若某一个方法被实现,取到的即是方法返回的值,后面的方法不再运行。如果是BOOL或者Int等值类型, 会将其包装成一个NSNumber对象。

  2. 若这三个方法都没有找到,则会调用+ (BOOL)accessInstanceVariablesDirectly方法判断是否允许取成员变量的值。若返回NO,直接调用- (nullable id)valueForUndefinedKey:(NSString *)key方法,并抛出异常 NSUnknowKeyException

  3. 若返回YES,会按先后顺序取_key、_isKey、 key、isKey成员变量的值。调用- (nullable id)valueForUndefinedKey:(NSString *)key方法。

补充

  1. KVC提供属性值正确性验证的API,它可以用来检查set的值是否正确、为不正确的值做一个替换值或者拒绝设置新值并返回错误原因。
- - (BOOL)validateValue:(inout id __nullable * __nonnull)ioValue forKey:(NSString *)inKey error:(out NSError **)outError;
  1. KVC中的异常.获取值时找不到key- (nullable id)valueForUndefinedKey:(NSString *)key;

  2. 设值时找不到key- (void)setValue:(nullable id)value forUndefinedKey:(NSString *)key;

  3. 给不能设置nil的属性设置了nil。

  • 如果你在SetValue方法时面给Value传nil,则会调用这个方法
  • (void)setNilValueForKey:(NSString *)key;

KVC/KVO 本质的更多相关文章

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

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

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

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

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

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

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

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

  5. kvc/kvo复习

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

  6. IOS开发之KVC KVO KVB

    KVC(Key Value Coding) KVO(Key Value Observing) KVB(Key Value Binding) KVO是Cocoa的一个重要机制,他提供了观察某一属性变化的 ...

  7. 04 KVC|KVO|Delegate|NSNotification区别

    一. iOS 中KVC.KVO.NSNotification.delegate 在实际的编程中运用的非常多,掌握好他们的运行原理和使用场合对于我们程序的开发将会带来事办工倍的效果:   二. KVC ...

  8. QF——OC中的KVC,KVO

    KVC: (Key Value Coding) 键值编码 所谓KVC,其实就是不通过set和get方法访问对象属性,而是通过属性名字符串动态的去读取属性.KVC其实也是OC反射机制的一种运用. 之所以 ...

  9. 【iOS 开发】Objective - C 面向对象 - 方法 | 成员变量 | 隐藏封装 | KVC | KVO | 初始化 | 多态

    一. Objective-C 方法详解 1. 方法属性 (1) OC 方法传参机制 Object-C 方法传参机制 : OC 中得参数传递都是值传递, 传入参数的是参数的副本; -- 基本类型 (值传 ...

随机推荐

  1. Boost-ioservices介绍

    IO模型 io_service对象是asio框架中的调度器,所有异步io事件都是通过它来分发处理的(io对象的构造函数中都需要传入一个io_service对象). asio::io_service i ...

  2. android自动化测试之uiautomator

    1.通过monkeyrunner.bat   monkey_record.py启动MonkeyRecorder进行拿到各个控件的坐标(要连上手机才可以启动) 2.也可以通过uiautomatorvie ...

  3. JavaScript-Tool-富文本:Simditor

    ylbtech-JavaScript-Tool-富文本:Simditor 1.返回顶部 1. 2. 2.返回顶部 1. Simditor 是团队协作工具 Tower 使用的富文本编辑器. 相比传统的编 ...

  4. CSS:CSS 合法颜色值

    ylbtech-CSS:CSS 合法颜色值 1.返回顶部 1. CSS 颜色 可以用以下方法来规定 CSS 中的颜色: 十六进制色 RGB 颜色 RGBA 颜色 HSL 颜色 HSLA 颜色 预定义/ ...

  5. [转]windows10 1703 鼠标右键打开命令提示符cmd

    https://answers.microsoft.com/zh-hans/windows/forum/windows_10-performance/windows10-1703/8bdfdfea-4 ...

  6. 爬虫库之BeautifulSoup学习(四)

    探索文档树: find_all(name,attrs,recursive,text,**kwargs) 方法搜索当前tag的所有tag子节点,并判断是否符合过滤器的条件 1.name参数,可以查找所有 ...

  7. PHP文件操作的经典案例

    <?php /* 遍历目录函数,只读取目录的最外层的内容 */ function readDirectory($path){ $handle = opendir($path); while(($ ...

  8. CSS小技巧收藏

    居中对齐 很多时候我们需要把一个元素在其父级容器里水平.垂直居中对齐.以下我列出了常用的几种方法: 1.在知道子元素宽度与高度的情况下进行居中,采用位置定位:absolute + margin .pa ...

  9. 无法序列化会话状态。请注意,当会话状态模式为“StateServer”或“SQLServer”时,不允许使用无法序列化的对象或 MarshalByRef 对象。

    原文链接:http://blog.csdn.net/byondocean/article/details/7564502 session是工作在你的应用程序进程中的.asp.net进程.iis往往会在 ...

  10. CodeForces717C 【数学】

    题意: 给你n个数既表示a类的值也表示b类的值,然后计算a和b类两两搭配相乘相加,使得答案最小: 思路: 显而易见的方案是最小乘最大,次小乘次大,然后依次下去.. 可以那个特例证明这个是对的 #inc ...