iOS开发底层之KVC了解 - 16

KVC是什么?

KVC全称Key-Value Coding(键值编码),是一种由NSKeyValueCoding非正式协议启用的机制,对象采用它来提供对其属性的间接访问。

当一个对象符合键值编码时,它的属性可以通过字符串Key来寻址。这种间接访问机制补充了实例变量及其关联的访问方法所提供的直接访问

API介绍:

  1. KVC的API在Foundation框架中
  2. KVC本质上是对NSObject、NSArray、NSDictionary、NSMutableDictionary、NSOrderedSet、NSSet等对象,实现NSKeyValueCoding分类,赋予它们Key-Value Coding的能力
  3. 通过Key读取和存储API
- (nullable id)valueForKey:(NSString *)key;
- (void)setValue:(nullable id)value forKey:(NSString *)key;
  1. 通过keyPath读取和存储API
- (nullable id)valueForKeyPath:(NSString *)keyPath; 
- (void)setValue:(nullable id)value forKeyPath:(NSString *)keyPath;

API使用:

1. 对象属性

属性:基础对象,例如变量、字符串或bool。值对象NSNumber和其他数值类型。
一对一的关系:这些是具有自己属性的可变对象。一个对象的属性可以在不改变对象本身的情况下改变

对多关系:这些是集合对象。通常使用NSArray或的实例NSSet来保存此类集合,也可能是自定义集合类型

  • 集合属性
mutableArrayValueForKey:和 mutableArrayValueForKeyPath:
它们返回一个行为类似于NSMutableArray对象的代理对象
mutableSetValueForKey:和mutableSetValueForKeyPath:
它们返回一个行为类似于NSMutableSet对象的代理对象
mutableOrderedSetValueForKey:和mutableOrderedSetValueForKeyPath:
它们返回一个行为类似于NSMutableOrderedSet对象的代理对象
  • 访问非对象属性
默认键值编码实现使用NSNumber实例包装的标量类型
默认存取用于包装和展开常见NSPoint、NSRange、NSRect、和NSSize结构
结构类型,可以包装在一个NSValue对象中
  • 验证属性
验证方法认为值对象有效并在YES不改变值或错误的情况下返回
验证方法认为值对象无效,但选择不更改它。在这种情况下,该方法返回NO并将错误引用(如果由调用者提供)设置为NSError指示失败原因的对象
验证方法认为值对象无效,但会创建一个新的有效对象作为替换。在这种情况下,该方法返回YES同时保持错误对象不变。在返回之前,该方法修改值引用以指向新的值对象。当它进行修改时,该方法总是创建一个新对象,而不是修改旧对象,即使值对象是可变的

KVC的存储过程:

【第一步】 查找是否存在以下三种setter方法,查找顺序:setKey→_setKey→setIsKey (key是指成员变量名,首字母大小写需要符合KVC的命名规范)

存在任意一种setter方法,直接设置属性的value

如果不存在进入下面步骤

【第二步】 查找accessInstanceVariablesDirectly方法的返回值

返回YES,查找间接访问的实例变量进行赋值,查找顺序:_→_is→→is

如果找到其中任意一个实例变量,可对其赋值

如果还未找到,进入下面步骤

【第三步】 如果setter方法或实例变量都没有找到,系统会调用该对象的setValue:forUndefinedKey:方法,默认抛出NSUndefinedKeyException类型的异常

KVC的读取过程:

【第一步】 查找getter方法,查找顺序:getKey→key→isKey→_key

如果找到,进入 **第五步**

如果未找到,进入 **第二步**

【第二步】查找countOf、objectInAtIndex:、AtIndexes: 下标寻找

如果找到第一个,则会创建一个响应所有NSArray方法的集合代理对象,并返回该对象,即:NSKeyValueArray,属于NSArray的子类。代理对象随后将接收到任何NSArray消息转换为countOf<Key>、objectIn<Key>AtIndex:<key>AtIndexes:消息的某种组合,用来创建键值编码对象

方法名的命名规则,要符合KVC的标准命名方法,包括方法签名

如果未找到,进入**第三步**

【第三步】查找以下几种方法,countOfKey、enumeratorOfKey、memberOfKey:

如果三个方法都找到,则会创建一个响应所有NSSet方法的集合代理对象,并返回该对象,此代理对象随后将其收到的所有NSSet消息转换为countOf<Key>、enumeratorOf<Key>、memberOf<Key>:消息的某种组合,用于创建它的对象

如果未找到,进入【第四步】

【第四步】查找accessInstanceVariablesDirectly方法的返回值

返回YES,依次搜索_<key>、_is<Key><key>is<Key>的实例变量

找到实例变量,直接获取实例变量的值,进入【第五步】

未找到,进入【第六步】

返回NO,进入【第六步】

【第五步】根据搜索到的属性值的类型,返回不同的结果

如果是对象指针,则直接返回结果

如果是NSNumber支持的标量类型,则将其存储在NSNumber实例中并返回它

如果是NSNumber不支持的标量类型,转换为NSValue对象并返回该对象

【第六步】如果以上所有方法都失败,系统调用该对象的valueForUndefinedKey:方法,默认抛出NSUndefinedKeyException类型的异常

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值