Objective-C(三) KVC

作者: 造轮子的锅 | 来源:发表于2020-01-16 16:20 被阅读0次

KVC

Key-Value Coding

  • 允许开发者通过key名直接访问对象的属性或者给属性赋值,可以将访问或修改属性的时机从编译时变成运行时。

对一般属性进行读取或者修改:

- (nullable id)valueForKey:(NSString *)key;                          //直接通过Key来取值

- (void)setValue:(nullable id)value forKey:(NSString *)key;          //通过Key来设值

- (nullable id)valueForKeyPath:(NSString *)keyPath;                  //通过KeyPath来取值

- (void)setValue:(nullable id)value forKeyPath:(NSString *)keyPath;  //通过KeyPath来设值

对有序集合KVC对应的方法:

-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>://可选的,如果在此类操作上有性能问题,就需要考虑实现之

无序集合KVC对应的方法:

-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>://这两个都是可选的,如果在此类操作上有性能问题,就需要考虑实现之

KVC一些特殊的方法:

+ (BOOL)accessInstanceVariablesDirectly;
//默认返回YES,表示如果没有找到Set<Key>方法的话,会按照_key,_iskey,key,iskey的顺序搜索成员,设置成NO就不这样搜索

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

- (NSMutableArray *)mutableArrayValueForKey:(NSString *)key;
//这是集合操作的API,里面还有一系列这样的API,如果属性是一个NSMutableArray,那么可以用这个方法来返回。

- (nullable id)valueForUndefinedKey:(NSString *)key;
//如果Key不存在,且没有KVC无法搜索到任何和Key有关的字段或者属性,则会调用这个方法,默认是抛出异常。

- (void)setValue:(nullable id)value forUndefinedKey:(NSString *)key;
//和上一个方法一样,但这个方法是设值。

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

- (NSDictionary<NSString *, id> *)dictionaryWithValuesForKeys:(NSArray<NSString *> *)keys;
//输入一组key,返回该组key对应的Value,再转成字典返回,用于将Model转到字典。


KVC赋值过程

  1. 程序优先调用set方法,通过setter完成设置。
  2. 如果set:方法没找到,KVC机制会检查+ (BOOL)accessInstanceVariablesDirectly方法有没有返回YES,默认该方法会返回YES,如果你重写了该方法让其返回NO的话,那么在这一步KVC会执行setValue:forUndefinedKey:方法,不过一般开发者不会这么做。所以KVC机制会搜索该类里面有没有名为_name的成员变量,无论该变量是在类接口处定义,还是在类实现处定义,也无论用了什么样的访问修饰符,只在存在以_命名的变量,KVC都可以对该成员变量赋值。
  3. 如果该类没有set:方法也没有_成员变量,KVC机制就会搜索_is的成员变量。
  4. 如果以上还未找到,KVC机制就会搜索is的成员变量。
  5. 以上都没有的话,系统将会执行该对象的setValue:forUndefinedKey:方法,默认是抛出异常。
  • 禁用kvc赋值只需要重写+ (BOOL)accessInstanceVariablesDirectly方法并返回no,当没有setter方法时,寻找key的相关变量执行就会停止。
  • 如果没有重写该方法,会按照set<Key>方法,_key,_isKey,key,iskey的顺序查找并进行赋值操作

KVC读取过程

-valueForKey:
1.首先按get,is的顺序搜索getter方法,找到的话直接调用,如果是基本数据类型会将其包装成一个NSNumber对象。
2.如果上面getter方法没有找到,KVC则会查找countOf,objectInAtIndex或AtIndexes格式的方法。如果找到那么就会返回一个可以响应NSArray所有方法的代理集合(NSKeyValueArray),调用这个代理集合的方法。还有一个可选的get:range:方法,想重新定义KVC的一些功能,可以添加这些方法,但是方法名需要符合KVC的标准命名方法,包括方法签名。
3.如果上面没有找到,就会同时查找countOf,enumeratorOf,memberOf格式的方法。如果这三个方法都找到就会返回一个响应NSSet的代理集合。如上面一样。
4.如果还没有找到,就会跟KVC赋值的时候一样,检查类方法+ (BOOL)accessInstanceVariablesDirectly。返回YES则会按_key,_isKey,isKey顺序搜索。如果返回NO,那么直接调用valueForUndefinedKey:方法,默认是抛出异常。

-valueForKeyPath:
会以小数点.来分割key,然后再按普通key来执行valueForKey的过程


KVC处理异常

kvc处理nil异常
当使用setValueForKey为对象赋值为key时,KVC会调用setNilValueForKey:方法,抛出异常,此时可以重写该方法。

kvc处理UndefinedKey异常
当key不存在时,会触发kvc的forUndefinedKey方法:

- (id)valueForUndefinedKey:(NSString *)key
- (void)setValue:(id)value forUndefinedKey:(NSString *)key 

此时可以重写这两个方法来避免崩溃。


补充

  • KVC可以用来处理数值和结构体类型
  • KVC可以来做键值做验证
  • KVC可以处理多级集合
  • KVC可以使用对象运送符和简单集合运算符

相关文章

  • KVO KVO 温习

    KVC 与 KVO 是 Objective-C 的关键概念. KVC: KVC,即是指 NSKeyValueCod...

  • iOS Objective-C KVC 详解

    iOS Objective-C KVC 详解 1. KVC简介 KVC 全称Key Value Coding,是苹...

  • KVC 和 KVO

    iOS-KVC和KVO精炼讲解(干货)KVC 和 KVOiOS开发系列--Objective-C之KVC、KVO细...

  • KVC

    iOS 如何使用KVC iOS开发UI篇—Kvc简单介绍 iOS开发系列--Objective-C之KVC、KVO

  • [转]KVO & KVC

    本文转自:Objective-C中的KVC和KVO. KVC KVO2.1. Registering for Ke...

  • Objective-C(三) KVC

    KVC Key-Value Coding 允许开发者通过key名直接访问对象的属性或者给属性赋值,可以将访问或修改...

  • iOS面试题:KVC的赋值和取值过程是怎样的?KVO原理是什么?

    更多:iOS面试题大全 1、KVC赋值 2、 KVC取值 3、 KVO原理 KVO 是 Objective-C 对...

  • KVC、KVO

    IOS开发系列--Objective-C之KVC、KVO - KenshinCui - 博客园

  • 探索Objective-C的KVC实现

    KVC Objective-C作为一门动态语言,NSObject 里面提供了动态取设值的方法 这就是 KVC (全...

  • 再次学习KVO 与 KVC

    简介 KVO 与KVC 是 充分利用了objective-c 动态语言特性的一种机制 KVO(同步运行) KVC

网友评论

    本文标题:Objective-C(三) KVC

    本文链接:https://www.haomeiwen.com/subject/gmetzctx.html