OC键值编码KVC

KVC全称是key-value coding的缩写,即键值编码技术。
KVC破坏了面向对象编程思想。

1.常用的API如下:

#直接通过Key来取值
- (nullable id)valueForKey:(NSString *)key;                         
#通过Key来设值
- (void)setValue:(nullable id)value forKey:(NSString *)key;          
#通过KeyPath来取值
- (nullable id)valueForKeyPath:(NSString *)keyPath;                 
#通过KeyPath来设值
- (void)setValue:(nullable id)value forKeyPath:(NSString *)keyPath; 

NSKeyValueCoding类别中其他的一些方法:

#默认返回YES,表示如果没有找到Set<Key>方法,会按照_key,_iskey,key,iskey的顺序搜索成员
#设置成NO就跳过匹配搜索,如果没有Set<Key>方法,直接抛出valueForUndefinedKey
+ (BOOL)accessInstanceVariablesDirectly;

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

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

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

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

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

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

如果开发者想让这个类禁用KVC里,那么重写
+ (BOOL)accessInstanceVariablesDirectly方法让其返回NO即可,这样的话如果KVC没有找到set<Key>:属性名时,会直接用setValue:forUndefinedKey:方法。

2.KVC流程:

  • 程序优先调用set<Key>:属性值方法,代码通过setter方法完成设置。注意,这里的<key>是指成员变量名,首字母大小写要符合KVC的命名规则

  • 如果没有找到setName:方法,KVC机制会检查+ (BOOL)accessInstanceVariablesDirectly方法有没有返回YES,默认该方法会返回YES。如果你重写了该方法让其返回NO的话,那么在这一步KVC会执行setValue:forUndefinedKey:方法终止流程。

  • 如果该类即没有set<key>:方法,KVC机制会搜索该类里面有没有名为<key>的成员变量,无论该变量是在类接口处定义,还是在类实现处定义,也无论用了什么样的访问修饰符,只在存在以<key>命名的变量,KVC都可以对该成员变量赋值。

  • 如果没有找到以<key>命名的变量,会继续搜索以_<key>_is<Key>命名的成员变量。

  • 如果以上都没找到,KVC机制再会继续搜索<key>is<Key>的成员变量。再给它们赋值。

  • 如果上面列出的方法或者成员变量都不存在,系统将会执行该对象的setValue:forUndefinedKey:方法,默认是抛出异常。

3.KVC处理集合

KVC同时还提供了很复杂的函数
1). 简单集合运算符共有@avg, @count , @max , @min ,@sum5种
例如:

        NSArray* arrBooks = @[book1,book2,book3,book4];
        NSNumber* sum = [arrBooks valueForKeyPath:@"@sum.price"];

2). 对象运算符比集合运算符稍微复杂,能以数组的方式返回指定的内容,一共有两种:
@distinctUnionOfObjects
@unionOfObjects
它们的返回值都是NSArray,区别是前者返回的元素都是唯一的,是去重以后的结果;后者返回的元素是全集。

4.KVC使用场景

  • 动态地取值和设值
    利用KVC动态的取值和设值是最基本的用途了。

  • 用KVC来访问和修改私有变量
    对于类里的私有属性,Objective-C是无法直接访问的,但是KVC是可以的。

  • Model和字典转换
    这是KVC强大作用的又一次体现,KVC和Objc的runtime组合可以很容易的实现Model和字典的转换。

  • 修改一些控件的内部属性
    这也是iOS开发中必不可少的小技巧。众所周知很多UI控件都由很多内部UI控件组合而成的,但是Apple度没有提供这访问这些控件的API,这样我们就无法正常地访问和修改这些控件的样式。
    而KVC在大多数情况可下可以解决这个问题。最常用的就是个性化UITextField中的placeHolderText了。

猜你喜欢

转载自blog.csdn.net/weixin_34090562/article/details/87375154
KVC