KVC定义
- KVC的全称是Key-Value Coding,翻译成中文是 键值编码。
- 键值编码是由NSKeyValueCoding非正式协议启用的一种机制,对象采用该协议来间接访问其属性。既可以通过一个字符串key来访问某个属性。这种间接访问机制补充了实例变量及其相关的访问器方法所提供的直接访问。
KVC常用API
///1.直接通过Key来取值
UIView *view = [[UIView alloc]initWithFrame:CGRectMake(0, 15, 50, 50)];
[self.view addSubview:view];
view.backgroundColor = [UIColor yellowColor];
view.alpha = 0.1;
NSLog(@"透明度为%@", [view valueForKey:@"alpha"]);
///2.通过Key来设值
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[view setValue:@"1" forKey:@"alpha"];
NSLog(@"新的透明度为%@", [view valueForKey:@"alpha"]);
});
///3.keyPath
/*通过KeyPath来取值
- (nullable id)valueForKeyPath:(NSString *)keyPath;
通过KeyPath来设值
- (void)setValue:(nullable id)value forKeyPath:(NSString *)keyPath;
*/
///4.其他
/**
//默认返回YES,表示如果没有找到Set<Key>方法的话,会按照_key,_iskey,key,iskey的顺序搜索成员,设置成NO就不这样搜索
+ (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修改属性会触发KVO吗?
会触发KVO KVC内部调用了相关方法
willChangeValueForKey:
<!--拿到成员变量直接修改-->
didChangeValueForKey:
KVC设值底层
/*
【第一步】首先查找是否有这三种setter方法,按照查找顺序为set<Key>:-> _set<Key> -> setIs<Key>
如果有其中任意一个setter方法,则直接设置属性的value(主注意:key是指成员变量名,首字符大小写需要符合KVC的命名规范)
如果都没有,则进入【第二步】
【第二步】:如果没有第一步中的三个简单的setter方法,则查找accessInstanceVariablesDirectly是否返回YES,
如果返回YES,则查找间接访问的实例变量进行赋值,查找顺序为:_<key> -> _is<Key> -> <key> -> is<Key>
如果找到其中任意一个实例变量,则赋值
如果都没有,则进入【第三步】
如果返回NO,则进入【第三步】
【第三步】如果setter方法 或者 实例变量都没有找到,系统会执行该对象的setValue:forUndefinedKey:方法,默认抛出NSUndefinedKeyException类型的异常
*/