关于KVC

介绍

通过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”

Created with Raphaël 2.2.0 setValue:属性值 forKey:@"name" setName:属性值 检查+ (BOOL)accessInstanceVarlblesdirectly _name _isName name isName setValue: forUndefinedKey: 抛出异常 yes no

KVC取值

Created with Raphaël 2.2.0 valueForKey:@"name" getName name isName countOfName objectInNameAtIndex nameAtIndexes (若countOfName和另外两个方法中的一个被找到) 返回一个可以响应NSArray所有方法的代理集合(NSKeyValueArray, NSArray的子类) 发送NSArray的方法,就会以countOfName, objectInNameAtIndex或nameAtIndexes的组合形式调用 可选getName: range: countOfName enumratorOfName memberOfName (若三个方法都找到) 返回一个可以响应NSSet所有方法的代理集合 发送NSSet的方法,就会以countOfName, enumratorOfName, memberOfName的组合形式调用 检查+ (BOOL)accessInstanceVariablesDirectly _name _isName name isName valueForUndefinedKey: yes no yes no yes no

KVC中的keyPath

分离key,用小数点.分割的key再像普通key一样

KVC处理异常

不小心使用错误的key或设置为nil
重写setNilForKey

KVC和容器类

不可变的有序容器属性(NSArray)和无序容器属性(NSSet)一般可以用valueForKey:来获取
而当对象的属性为可变的容器时
对于有序的容器:


Created with Raphaël 2.2.0 - (NSMutableArray *)mutableArrayValueForKey:(NSString *)key; key = @"name" insertObject: inNameAtIndex: removeObjectFromNameAtIndex: 或者 insertNameAtIndexes removeNameAtIndexes 如果至少找到一个insert和一个remove 返回一个可以响应NSMutableArray的代理集合(NSKeyValueFastMutableArray2) 发送方法,以上面方法的组合形式调用 两个可选实现接口:replaceObjectAtIndex: withObject replaceNameAtIndex: withName setName: 代理集合NSMutableArray会调用setName: (效率低) 检查+ (BOOL)accessInstanceVariablesDirectly; _name name valueForUndefinedKey: yes no yes no yes no

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的使用

  1. 动态地取值和设值
  2. KVC来访问和修改私有变量
  3. model和字典转换
  4. 修改一些控件的内部属性: UITextFieldplaceHolder的文字样式
  5. 操作集合:
    1). 用KVC实现高阶消息传递
    当容器类使用KVC时,valueForKey:将被传递给容器中的每一个对象,而不是容器本身进行操作
    2). 用KVC中的函数操作集合
    a. 简单的集合运算符: @avg @count @max @min @sum
    b. 对象运算符
    能以数组的方式返回指定的内容
    @distinctUnionOfObjects 返回NSArray 元素唯一 去重以后的结果
    @unionOfObjects 返回NSArray 全集
    c. ArraySet操作符
    集合中包含集合
    @distinctUnionOfArrays 返回一个数组,数组包含不同对象,不同的对象是在从关键路径到操作器右边的被指定的属性里
    @unionOfArrays 返回一个数组,和@distinctUnionOfArrays不一样,重复对象不会被移除
    @distinctUnionOfSets@distinctUnionOfArrays类似,因为Set本身就不支持重复

结束

猜你喜欢

转载自blog.csdn.net/weixin_42983482/article/details/83588401
KVC