【转】 KVC/KVO原理详解及编程指南
一、简介
1、KVC简介
2、KVO简介
二、KVC相关技术
1、Key和Key Path
- - (id)valueForKey:(NSString *)key;
- - (void)setValue:(id)value forKey:(NSString *)key;
- - (id)valueForKeyPath:(NSString *)keyPath;
- - (void)setValue:(id)value forKeyPath:(NSString *)keyPath;
面两个方法用到的KeyPath是一个被点操作符隔开的用于访问对象的指定属性的字符串序列。比如KeyPath
address.street将会访问消息接收对象所包含的address属性中包含的一个street属性。其实KeyPath说白了就是我们平时使用
点操作访问某个对象的属性时所写的那个字符串。
2、点语法和KVC
3、一对多关系(To-Many)中的集合访问器方法
们平时大部分使用的属性都是一对一关系(To-One),比如Person类中的name属性,每个人只有一个名字。但也有一对多的关系,比如
Person中有一个friendsName属性,这是个集合(在Objective-C中可以是NSArray,NSSet等),保存的是一个人的所有
朋友的名字。
- -countOf<Key>
- //必须实现,对应于NSArray的基本方法count:
- -objectIn<Key>AtIndex:
- -<key>AtIndexes:
- //这两个必须实现一个,对应于 NSArray 的方法 objectAtIndex: 和 objectsAtIndexes:
- -get<Key>:range:
- //不是必须实现的,但实现后可以提高性能,其对应于 NSArray 方法 getObjects:range:
- -insertObject:in<Key>AtIndex:
- -insert<Key>:atIndexes:
- //两个必须实现一个,类似于 NSMutableArray 的方法 insertObject:atIndex: 和 insertObjects:atIndexes:
- -removeObjectFrom<Key>AtIndex:
- -remove<Key>AtIndexes:
- //两个必须实现一个,类似于 NSMutableArray 的方法 removeObjectAtIndex: 和 removeObjectsAtIndexes:
- -replaceObjectIn<Key>AtIndex:withObject:
- -replace<Key>AtIndexes:with<Key>:
- //可选的,如果在此类操作上有性能问题,就需要考虑实现之
- -countOf<Key>
- //必须实现,对应于NSArray的基本方法count:
- -objectIn<Key>AtIndex:
- -<key>AtIndexes:
- //这两个必须实现一个,对应于 NSArray 的方法 objectAtIndex: 和 objectsAtIndexes:
- -get<Key>:range:
- //不是必须实现的,但实现后可以提高性能,其对应于 NSArray 方法 getObjects:range:
- -insertObject:in<Key>AtIndex:
- -insert<Key>:atIndexes:
- //两个必须实现一个,类似于 NSMutableArray 的方法 insertObject:atIndex: 和 insertObjects:atIndexes:
- -removeObjectFrom<Key>AtIndex:
- -remove<Key>AtIndexes:
- //两个必须实现一个,类似于 NSMutableArray 的方法 removeObjectAtIndex: 和 removeObjectsAtIndexes:
- -replaceObjectIn<Key>AtIndex:withObject:
- -replace<Key>AtIndexes:with<Key>:
- //这两个都是可选的,如果在此类操作上有性能问题,就需要考虑实现之
4、键值验证(Key-Value Validation)
- - (BOOL)validateValue:(inout id *)ioValue forKey:(NSString *)inKey error:(out NSError **)outError;
- - (BOOL)validate<Key>:error:
- -(BOOL)validateName:(id *)ioValue error:(NSError * __autoreleasing *)outError {
- // Implementation specific code.
- return ...;
- }
5、KVC对数值和结构体型属性的支持
- [person setValue:[NSNumber numberWithInteger:5] forKey:@"age"];
- [person valueForKey:@"age"];
这时,会以NSNumber的形式返回age的值。
- + (NSNumber *)numberWithChar:(char)value;
- + (NSNumber *)numberWithUnsignedChar:(unsigned char)value;
- + (NSNumber *)numberWithShort:(short)value;
- + (NSNumber *)numberWithUnsignedShort:(unsigned short)value;
- + (NSNumber *)numberWithInt:(int)value;
- + (NSNumber *)numberWithUnsignedInt:(unsigned int)value;
- + (NSNumber *)numberWithLong:(long)value;
- + (NSNumber *)numberWithUnsignedLong:(unsigned long)value;
- + (NSNumber *)numberWithLongLong:(long long)value;
- + (NSNumber *)numberWithUnsignedLongLong:(unsigned long long)value;
- + (NSNumber *)numberWithFloat:(float)value;
- + (NSNumber *)numberWithDouble:(double)value;
- + (NSNumber *)numberWithBool:(BOOL)value;
- + (NSNumber *)numberWithInteger:(NSInteger)value NS_AVAILABLE(10_5, 2_0);
- + (NSNumber *)numberWithUnsignedInteger:(NSUInteger)value NS_AVAILABLE(10_5, 2_0);
总之就是一些常见的数值型数据。
- + (NSValue *)valueWithCGPoint:(CGPoint)point;
- + (NSValue *)valueWithCGSize:(CGSize)size;
- + (NSValue *)valueWithCGRect:(CGRect)rect;
- + (NSValue *)valueWithCGAffineTransform:(CGAffineTransform)transform;
- + (NSValue *)valueWithUIEdgeInsets:(UIEdgeInsets)insets;
- + (NSValue *)valueWithUIOffset:(UIOffset)insets NS_AVAILABLE_IOS(5_0);
6、集合运算符(Collection Operators)
- NSNumber *transactionAverage = [transactions valueForKeyPath:@"@avg.amount"];
- NSNumber *numberOfTransactions = [transactions valueForKeyPath:@"@count"];
- @distinctUnionOfObjects
- @unionOfObjects
它们的返回值都是NSArray,区别是前者返回的元素都是唯一的,是去重以后的结果;后者返回的元素是全集。
- NSArray *payees = [transactions valueForKeyPath:@"@distinctUnionOfObjects.payee"];
- NSArray *payees = [transactions valueForKeyPath:@"@unionOfObjects.payee"];
前者会将收款人的姓名去除重复的以后返回,后者直接返回所有收款人的姓名。
- // Create the array that contains additional arrays.
- self.arrayOfTransactionsArray = [NSMutableArray array];
- // Add the array of objects used in the above examples.
- [arrayOfTransactionsArray addObject:transactions];
- // Add a second array of objects; this array contains alternate values.
- [arrayOfTransactionsArrays addObject:moreTransactions];
得到了一个包含集合的集合:arrayOfTransactionsArray
- @distinctUnionOfArrays
- @unionOfArrays
- @distinctUnionOfSets
- NSArray *payees = [arrayOfTransactionsArrays valueForKeyPath:@"@unionOfArrays.payee"];
三、实现原理
1、KVC如何访问属性值
2、KVC/KVO实现原理
派生类在被重写的 setter 方法实现真正的通知机制,就如前面手动实现键值观察那样。这么做是基于设置属性会调用 setter 方法,而通过重写就获得了 KVO 需要的通知机制。当然前提是要通过遵循 KVO 的属性设置方式来变更属性值,如果仅是直接修改属性对应的成员变量,是无法实现 KVO 的。
同时派生类还重写了 class 方法以“欺骗”外部调用者它就是起初的那个类。然后系统将这个对象的 isa
指针指向这个新诞生的派生类,因此这个对象就成为该派生类的对象了,因而在该对象上对 setter 的调用就会调用重写的
setter,从而激活键值通知机制。此外,派生类还重写了 dealloc 方法来释放资源。
- NSLog(@"self->isa:%@",self->isa);
- NSLog(@"self class:%@",[self class]);
- self->isa:Person
- self class:Person
- self->isa:NSKVONotifying_Person
- self class:Person
- - (void)willChangeValueForKey:(NSString *)key
- - (void)didChangeValueForKey:(NSString *)key
- - (void)observeValueForKeyPath:(NSString *)keyPath
- ofObject:(id)object
- change:(NSDictionary *)change
- context:(void *)context
- - (void)willChangeValueForKey:(NSString *)key
- - (void)didChangeValueForKey:(NSString *)key
四、优点和缺点
1、优点
2、缺点
心思想是说KVO的回调机制,不能传一个selector或者block作为回调,而必须重写
-addObserver:forKeyPath:options:context:方法所引发的一系列问题。问了解决这个问题,作者还亲自实现了一个
MAKVONotificationCenter类,代码见github:
版权声明:本文为博主原创文章,未经博主允许不得转载。
【转】 KVC/KVO原理详解及编程指南的更多相关文章
- KVC/KVO原理详解及编程指南
一.简介 1.KVC简介 2.KVO简介 二.KVC相关技术 1.Key和Key Path 2.点语法和KVC 3.一对多关系(To-Many)中的集合访问器方法 4.键值验证(Key-Value V ...
- 转:KVC/KVO原理详解及编程指南
作者:wangzz 原文地址:http://blog.csdn.net/wzzvictory/article/details/9674431 转载请注明出处 如果觉得文章对你有所帮助,请通过留言或 ...
- Java网络编程和NIO详解6:Linux epoll实现原理详解
Java网络编程和NIO详解6:Linux epoll实现原理详解 本系列文章首发于我的个人博客:https://h2pl.github.io/ 欢迎阅览我的CSDN专栏:Java网络编程和NIO h ...
- LVS原理详解(3种工作方式8种调度算法)--老男孩
一.LVS原理详解(4种工作方式8种调度算法) 集群简介 集群就是一组独立的计算机,协同工作,对外提供服务.对客户端来说像是一台服务器提供服务. LVS在企业架构中的位置: 以上的架构只是众多企业里面 ...
- [No0000126]SSL/TLS原理详解与WCF中的WS-Security
SSL/TLS作为一种互联网安全加密技术 1. SSL/TLS概览 1.1 整体结构 SSL是一个介于HTTP协议与TCP之间的一个可选层,其位置大致如下: SSL:(Secure Socket La ...
- LVS原理详解(3种工作模式及8种调度算法)
2017年1月12日, 星期四 LVS原理详解(3种工作模式及8种调度算法) LVS原理详解及部署之二:LVS原理详解(3种工作方式8种调度算法) 作者:woshiliwentong 发布日期: ...
- 【动画消消乐】HTML+CSS 自定义加载动画:清新折叠方块效果 063(附源码及原理详解)
前言 Hello!小伙伴! 非常感谢您阅读海轰的文章,倘若文中有错误的地方,欢迎您指出- 自我介绍ଘ(੭ˊᵕˋ)੭ 昵称:海轰 标签:程序猿|C++选手|学生 简介:因C语言结识编程,随后转入计算机专 ...
- Spring框架系列(6) - Spring IOC实现原理详解之IOC体系结构设计
在对IoC有了初步的认知后,我们开始对IOC的实现原理进行深入理解.本文将帮助你站在设计者的角度去看IOC最顶层的结构设计.@pdai Spring框架系列(6) - Spring IOC实现原理详解 ...
- Spring框架系列(7) - Spring IOC实现原理详解之IOC初始化流程
上文,我们看了IOC设计要点和设计结构:紧接着这篇,我们可以看下源码的实现了:Spring如何实现将资源配置(以xml配置为例)通过加载,解析,生成BeanDefination并注册到IoC容器中的. ...
随机推荐
- Linq打印
Method syntax: Enumerable.Range(1, 100).ToList().ForEach(Console.WriteLine); Query syntax: (from n i ...
- Linux Kernel 多个本地拒绝服务漏洞
漏洞名称: Linux Kernel 多个本地拒绝服务漏洞 CNNVD编号: CNNVD-201308-154 发布时间: 2013-08-12 更新时间: 2013-08-12 危害等级: 漏 ...
- 【转】更新SDK后,打包APK时报 the zipalign tool was not found in the sdk
原文网址:http://wyong.blog.51cto.com/1115465/1546632 原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任 ...
- eclipse常见错误
1.The superclass “javax.servlet.http.httpservlet” is not found in the build path 原因:未添加server librar ...
- HDU-4925 Apple Tree
http://acm.hdu.edu.cn/showproblem.php?pid=4925 Apple Tree Time Limit: 2000/1000 MS (Java/Others) ...
- git入门超详细(转载)
转自:http://www.cnblogs.com/tugenhua0707/p/4050072.html Git使用教程 一:Git是什么? Git是目前世界上最先进的分布式版本控制系统. 二:SV ...
- jQuery、实例大全
文章出处 http://www.cnblogs.com/suoning/p/5683047.html 一.简介 定义 jQuery创始人是美国John Resig,是优秀的Javascript框架: ...
- Centos 下安装MongoDB
Centos 下安装MongoDB 一.安装方法 方法(一) 1 配置包管理系统 创建/etc/yum.repos.d/mongodb.repo 文件,当然我们使用的是64位系统,32位的情况不再考 ...
- sBPM产品介绍
作者:CppExplore http://www.cppblog.com/CppExplore/和 http://blog.csdn.net/cppexplore同步发布. 近3年没发文章,谨以本 ...
- C++ —— 时间与日期
导读 在平时编程中有时需要获取当前的时间或者日期,然而不同的平台不同的场景下,有时使用的API也不尽相同.一般来说,C/C++中关于时间的标准库函数在不同的平台的都可以使用,可一些与平台相关的函数就只 ...