介绍
通过key
名直接访问对象的属性,或者给对象的属性赋值.在运行时动态地访问和修改对象的属性,而不是在编译时确定.
NSObject
的扩展来实现的(NSKeyValueCoding
)
最重要的四个方法
- (nullable id)valueForKey:(NSString *) key;
- (void)setValue:(nullable id)value forKey:(NSString *)key;
- (nullable id)valueForKeyPath:(NSString *)keyPath;
- (void)setValue:(nullable id)value forKeyPath:(NSString *)keyPath;
在NSKeyValueCoding
中还有其他一些方法:
//默认返回YES,表示没有搜索到setKey方法的话,会按照_key,_isKey,key,isKey的顺序搜索.设置为NO则不搜索
+ (BOOL)accessInstanceVariblesDirectly;
//KVC提供属性正确性验证的API
- (BOOL)validateValue:(inout id __nullable *_nonnull)ioValue forKey:(NSString *)inKey error:(out NSError **)outError;
//集合操作的API,如果属性为NSMutableArray,可以用这个方法
- (NSMutableArray *)mutableArrayValueForKey:(NSString *)key;
//若key不存在且KVC无法搜索到,则会调用,默认抛出异常
- (nullable id)valueForUndefinedKey:(NSString *)key;
//设置,同上
- (void)setValue:(nullable id)value forUndefinedKey:(NSString *)key;
//给value传nil,会调用这个方法
- (void)setNilValueForKey:(NSString *)key;
//输入一组key,返回该组key对应的value,再转为字典返回,用model转到字典
- (NSDictionary<NSString *, id> *)dictionaryWithValuesForKeys:(NSArray<NSString *> *)keys;
KVC设值
setValue:属性值 forKey:@“name”
KVC取值
KVC中的keyPath
分离key
,用小数点.分割的key
再像普通key
一样
KVC处理异常
不小心使用错误的key
或设置为nil
重写setNilForKey
KVC和容器类
不可变的有序容器属性(NSArray
)和无序容器属性(NSSet
)一般可以用valueForKey:
来获取
而当对象的属性为可变的容器时
对于有序的容器:
mutableArrayValueForKey:
的使用场景:
对NSMutableArray
添加observer
若对象属性是个NSMutableArray, NSMutableSet, NSMutableDictionary.
你添加KVO
,添加或移除元素不能接收到变化.
KVO
的本质是系统检测到某个属性的内存地址或常量改变时,会添加上- (void)willChangeValueForKey:(NSString *)key
和- (void)didChangeValueForKey:(NSString *)key
方法来发送通知.
使用mutableArrayValueForKey:
就可以
对于无序的容器:
- (NSMutableSet *)mutableSetValueForKey:(NSString *)key;
类似于NSMutableArray
的搜索过程.
keyPath
版本:
- (NSMutableArray *)mutableArrayValueForKeyPath:(NSString *)keyPath;
- (NSMutableSet *)mutableSetValueForKeyPath:(NSString *)keyPath;
KVC和字典
NSDictionary
使用KVC
,valueForKey:
的表现行为和objectForKey:
一样,所以使用valueForKeyPath:
用来访问多层嵌套的字典比较方便
- (NSDictionary<NSString *, id> *)dictionaryWithValuesForKeys:(NSArray<NSString *> *)keys;
- (void)setValuesForKeysWithDictionary:(NSDictionary<NSString *, id> *)keyedValues;
KVC的正确性验证
- (BOOL)validateValue:(inout id __nullable *__nonnull)ioValue forKey:(NSString *)inKey error:(out NSError **)outErrorl
默认实现是去探索类里面是否有一个这样的方法:- (BOOL)validateName: error:
若有,会调用
没有返回YES
KVC
不会主动去验证,需要开发者自己去调用
KVC的使用
- 动态地取值和设值
- 用
KVC
来访问和修改私有变量 model
和字典转换- 修改一些控件的内部属性:
UITextField
的placeHolder
的文字样式 - 操作集合:
1). 用KVC
实现高阶消息传递
当容器类使用KVC
时,valueForKey:
将被传递给容器中的每一个对象,而不是容器本身进行操作
2). 用KVC
中的函数操作集合
a. 简单的集合运算符:@avg @count @max @min @sum
b. 对象运算符
能以数组的方式返回指定的内容
@distinctUnionOfObjects
返回NSArray
元素唯一 去重以后的结果
@unionOfObjects
返回NSArray
全集
c.Array
和Set
操作符
集合中包含集合
@distinctUnionOfArrays
返回一个数组,数组包含不同对象,不同的对象是在从关键路径到操作器右边的被指定的属性里
@unionOfArrays
返回一个数组,和@distinctUnionOfArrays
不一样,重复对象不会被移除
@distinctUnionOfSets
和@distinctUnionOfArrays
类似,因为Set
本身就不支持重复
结束