博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
KVC搜索规则
阅读量:7310 次
发布时间:2019-06-30

本文共 2886 字,大约阅读时间需要 9 分钟。

搜索规则

KVC在通过key或者keyPath进行操作的时候,可以查找属性方法、成员变量等,查找的时候可以兼容多种命名。具体的查找规则要以官方文档为主,所以我把官方文档翻译了一下写在下面。

在KVC的实现中,依赖setter和getter的方法实现,所以方法命名应该符合苹果要求的规范,否则会导致KVC失败
在学习KVC的搜索规则前,要先弄明白一个属性的作用,这个属性在搜索过程中起到很重要的作用。这个属性表示是否允许读取实例变量的值,如果为YES则在KVC查找的过程中,从内存中读取属性实例变量的值。

@property (class, readonly) BOOL accessInstanceVariablesDirectly;复制代码

基础Getter搜索模式

1.这是valueForKey:的默认实现,给定一个key当做输入参数,开始下面的步骤,在这个接收valueForKey:方法调用的类内部进行操作.
通过getter方法搜索实例,例如get,is,的拼接方案。按照这个顺序,如果发现符合的方法,就调用对应的方法并拿着结果跳转到第五步。否则,就继续到下一步。
2.如果没有找到简单的getter方法,则搜索其匹配模式的方法countOf、objectInAtIndex:、AtIndexes:。 如果找到其中的第一个和其他两个中的一个,则创建一个集合代理对象,该对象响应所有NSArray的方法并返回该对象。否则,继续到第三步。
代理对象随后将NSArray接收到的countOf、objectInAtIndex:、AtIndexes:的消息给符合KVC规则的调用方。
当代理对象和KVC调用方通过上面方法一起工作时,就会允许其行为类似于NSArray一样。
3.如果没有找到NSArray简单存取方法,或者NSArray存取方法组。则查找有没有countOf、enumeratorOf、memberOf:命名的方法.
如果找到三个方法,则创建一个集合代理对象,该对象响应所有NSSet方法并返回。否则,继续执行第四步.
此代理对象随后转换countOf、enumeratorOf、memberOf:方法调用到创建它的对象上。实际上,这个代理对象和NSSet一起工作,使得其表象上看起来是NSSet。
4.如果没有发现简单getter方法,或集合存取方法组,以及接收类方法accessInstanceVariablesDirectly是返回YES的。搜索一个名为
、_is、、is的实例,根据他们的顺序。
如果发现对应的实例,则立刻获得实例可用的值并跳转到第五步,否则,跳转到第六步。
5.如果取回的是一个对象指针,则直接返回这个结果.
如果取回的是一个基础数据类型,但是这个基础数据类型是被NSNumber支持的,则存储为NSNumber并返回.
如果取回的是一个不支持NSNumber的基础数据类型,则通过NSValue进行存储并返回.
6.如果所有情况都失败,则调用valueForUndefinedKey:方法并抛出异常,这是默认行为。但是子类可以重写此方法.

基础Setter搜索模式

这是setValue:forKey:的默认实现,给定输入参数value和key。试图在接收调用对象的内部,设置属性名为key的value,通过下面的步骤:
1.查找set:或_set命名的setter,按照这个顺序,如果找到的话,调用这个方法并将值传进去(根据需要进行对象转换)。
2.如果没有发现一个简单的setter,但是accessInstanceVariablesDirectly类属性返回YES,则查找一个命名规则为_、_is、is的实例变量。根据这个顺序,如果发现则将value赋值给实例变量。
3.如果没有发现setter或实例变量,则调用setValue:forUndefinedKey:方法,并默认提出一个异常,但是一个NSObject的子类可以提出合适的行为。
NSMutableArray搜索模式
这是mutableArrayValueForKey:的默认实现,给一个key当做输入参数。在接收访问器调用的对象中,返回一个名为key的可变代理数组,这个代理数组就是用来响应外界KVO的对象,通过下面的步骤进行查找:
1.查找一对方法insertObject:inAtIndex:和removeObjectFromAtIndex:(相当于NSMutableArray的原始方法insertObject:atIndex:和removeObjectAtIndex:)或者方法名是insert:atIndexes:和removeAtIndexes:(相当于NSMutableArray的原始方法insertObjects:atIndexes:和removeObjectsAtIndexes:)。

如果找到最少一个insert方法和最少一个remove方法,则返回一个代理对象,来响应发送给NSMutableArray的组合消息insertObject:inAtIndex:、removeObjectFromAtIndex:、insert:atIndexes:,和removeAtIndexes:消息。

当对象接收一个mutableArrayValueForKey:消息并实现可选替换方法,例如replaceObjectInAtIndex:withObject:或replaceAtIndexes:with:方法,代理对象会在适当的情况下使用它们,以获得最佳性能。

2.如果对象没有可变数组方法,查找一个替代方法,命名格式为set:。在这种情况下,向mutableArrayValueForKey:的原始响应者发送一个set:消息,来返回一个代理对象来响应NSMutableArray事件。

提示:
这一步描述的机制远不如上一步有效,因为它可能重复创建新的集合对象,而不是修改现有的对象。因此,在自己设计的KVC时应该尽量避免它。

3.如果没有可变数组的方法,也没有找到访问器,但接受响应的类accessInstanceVariablesDirectly属性返回YES,则查找一个名为_或的实例变量。

按照这个顺序,如果找到实例变量,则返回一个代理对象。改对象将接收所有NSMutableArray发送过来的消息,通常是NSMutableArray或其子类。

4.如果所有情况都失败,则返回一个可变的集合代理对象。当它接收NSMutableArray消息时,发送一个setValue:forUndefinedKey:消息给接收mutableArrayValueForKey:消息的原始对象。

这个setValue:forUndefinedKey:的默认实现是提出一个NSUndefinedKeyException异常,但是子类可以重写这个实现。

转载于:https://juejin.im/post/5baa5b75e51d450e9d64a0b0

你可能感兴趣的文章
Gearman Server 使用 MySQL UDFs 来管理和保持队列
查看>>
Java Magic. Part 1: java.net.URL
查看>>
Java 8系列之重新认识HashMap
查看>>
JAVA CAS单点登录之三:CAS代理模式演练
查看>>
js 构造函数继承
查看>>
Riak存储引擎bitcask与leveldb测试
查看>>
node常用模块
查看>>
OURS-S3C2410RP常见问题
查看>>
我的友情链接
查看>>
数据仓库入门(实验5)添加维度
查看>>
解决SQL出现15023错误,提示用户已存在
查看>>
解决Android系统下某些手机RadioButton无法居中(如三星G3508)
查看>>
Java 之建造者模式
查看>>
mysql死锁解决方法
查看>>
Mybatis传值方式
查看>>
网站知名度如何提高
查看>>
python类的使用
查看>>
基于postfix邮件网关搭建
查看>>
指数预测模型
查看>>
我的友情链接
查看>>