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 ,@sum
5种
例如:
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了。
网友评论