1.kvc:Key-Value Coding
- 基本类型使用
- (void)setValue:(nullable id)value forKey:(NSString *)key;
- (nullable id)valueForKey:(NSString *)key;
- 集合类型使用
@property (nonatomic, strong) NSArray *array;
// 修改不可变数组array的第一个值,
person.array = @[@"1",@"2",@"3"];
// 方法一,修改为888
NSArray *array = @[@"888",@"2",@"3"];
[person setValue:array forKey:@"array"];
NSLog(@"方法1:array = %@",[person valueForKey:@"array"]);
// 放方二,kvc的方法,修改为999
NSMutableArray *ma = [person mutableArrayValueForKey:@"array"];
ma[0] = @"999";
NSLog(@"方法2:array = %@",[person valueForKey:@"array"]);
// 打印值
2020-02-13 19:30:11.594007+0800 001-KVC简介[51813:1163702] 方法1:array = (
888,
2,
3
)
2020-02-13 19:30:11.594277+0800 001-KVC简介[51813:1163702] 方法2:array = (
999,
2,
3
)
- 非对象类型,转换成相应的NSValue,取值的时候,使用getValue接收取到的reslutValue值
ThreeFloats floats = {1., 2., 3.};
NSValue *value = [NSValue valueWithBytes:&floats objCType:@encode(ThreeFloats)];
[person setValue:value forKey:@"threeFloats"];
NSValue *reslutValue = [person valueForKey:@"threeFloats"];
NSLog(@"value = %@",reslutValue);
// 创建一个同类型结构体用来接收reslutValue
ThreeFloats th;
[reslutValue getValue:&th] ;
NSLog(@"%f - %f - %f",th.x,th.y,th.z);
// 打印值
2020-02-13 19:44:07.411199+0800 001-KVC简介[51917:1170877] value = {length = 12, bytes = 0x0000803f0000004000004040}
2020-02-13 19:44:07.411318+0800 001-KVC简介[51917:1170877] 1.000000 - 2.000000 - 3.000000
2. kvc的赋值过程 Setter
- 官方文档
1.进行setter方法查找,
2.进行成员变量查找,
3.未找到则调用setValue:forUndefinedKey
准备测试类验证
@interface KVCObject : NSObject
{
@public
NSString *_name;
NSString *_isName;
NSString *name;
NSString *isName;
}
@end
KVCObject *ko = [KVCObject new];
// 1: KVC - 赋值过程
[ko setValue:@"kvc_name" forKey:@"name"];
2.1 set or _set 调用
会依次调用setKey,_setKey,setIsKey这三种方法
不会调用_setIsKey,此方法不被调用
setter方法顺序验证
- (void)setName:(NSString *)name{
NSLog(@"%s - %@",__func__,name);
}
- (void)_setName:(NSString *)name{
NSLog(@"%s - %@",__func__,name);
}
- (void)setIsName:(NSString *)name{
NSLog(@"%s - %@",__func__,name);
}
- 依次访问顺序
KVC取值&赋值过程[52000:1175468] -[KVCObject setName:] - kvc_name
KVC取值&赋值过程[52021:1177222] -[KVCObject _setName:] - kvc_name
KVC取值&赋值过程[52033:1177853] -[KVCObject setIsName:] - kvc_name
2.2 成员变量赋值顺序
当2.1寻找未果,并且accessInstanceVariablesDirectly返回YES的时候,会进行成员变量查找,如果返回NO,则跳过该步骤,直接到最后一步setValue: forUndefinedKey:
验证代码
NSLog(@"_name = %@",ko->_name);
NSLog(@"_isName = %@",ko->_isName);
NSLog(@"name = %@",ko->name);
NSLog(@"isName = %@",ko->isName);
2.2.1 当accessInstanceVariablesDirectly返回NO
+ (BOOL)accessInstanceVariablesDirectly {
return NO;
}
- 结果如下,所有成员变量均未被赋值
2020-02-13 20:49:11.858754+0800 002-KVC取值&赋值过程[52465:1208541] name is Undefined
2020-02-13 20:49:11.858923+0800 002-KVC取值&赋值过程[52465:1208541] _name = (null)
2020-02-13 20:49:11.859015+0800 002-KVC取值&赋值过程[52465:1208541] _isName = (null)
2020-02-13 20:49:11.859231+0800 002-KVC取值&赋值过程[52465:1208541] name = (null)
2020-02-13 20:49:11.859378+0800 002-KVC取值&赋值过程[52465:1208541] isName = (null)
2.2.2 当accessInstanceVariablesDirectly返回YES
- 开始查找成员变量
- 顺序: _
, _is , , or is
// 1. 四个成员变量均在_name,_isName,name,isName
2020-02-13 20:12:32.219946+0800 002-KVC取值&赋值过程[52173:1188008] _name = kvc_name
2020-02-13 20:12:32.220073+0800 002-KVC取值&赋值过程[52173:1188008] _isName = (null)
2020-02-13 20:12:32.220160+0800 002-KVC取值&赋值过程[52173:1188008] name = (null)
2020-02-13 20:12:32.220237+0800 002-KVC取值&赋值过程[52173:1188008] isName (null)
// 2. 三个成员变量均在 _isName, name, isName
2020-02-13 20:13:06.580442+0800 002-KVC取值&赋值过程[52191:1188733] _isName = kvc_name
2020-02-13 20:13:06.580567+0800 002-KVC取值&赋值过程[52191:1188733] name = (null)
2020-02-13 20:13:06.580659+0800 002-KVC取值&赋值过程[52191:1188733] isName (null)
// 3. 两个成员变量均在 name, isName
2020-02-13 20:20:08.235096+0800 002-KVC取值&赋值过程[52255:1193023] name = kvc_name
2020-02-13 20:20:08.235226+0800 002-KVC取值&赋值过程[52255:1193023] isName = (null)
// 4. 只剩一个成员变量均在 isName
2020-02-13 20:20:46.698804+0800 002-KVC取值&赋值过程[52271:1193754] isName = kvc_name
2.3 未找到所需要的key时
- (void)setValue:(id)value forUndefinedKey:(NSString *)key {
NSLog(@"%@ is Undefined", key);
}
// 打印
2020-02-13 20:46:31.007423+0800 002-KVC取值&赋值过程[52421:1206111] name is Undefined
3. kvc的取值过程 Getter(下面为非集合类型取值过程)
- 1.getter方法取值,如果去到值直接返回
- 2.accessInstanceVariablesDirectly返回YES,然后访问成员变量
- 3.valueForUndefinedKey
ko->_name = @"_name";
ko->_isName = @"_isName";
ko->name = @"name";
ko->isName = @"isName";
NSLog(@"取值:name = %@",[person valueForKey:@"name"]);
3.1 getter方法查找
- 调用顺序: get
, , is , or _ - 验证
// getter方法
- (NSString *)getName{
return @"getter: getName";
}
- (NSString *)name{
return @"getter: name";
}
- (NSString *)isName{
return @"getter: isName";
}
- (NSString *)_name{
return @"getter: _name";
}
- 结果
// 1
2020-02-13 21:02:29.167715+0800 002-KVC取值&赋值过程[52536:1214478] 取值:name = getter: getName
// 2
2020-02-13 21:04:11.983149+0800 002-KVC取值&赋值过程[52556:1215778] 取值:name = getter: name
// 3
2020-02-13 21:04:35.398485+0800 002-KVC取值&赋值过程[52571:1216422] 取值:name = getter: isName
// 4
2020-02-13 21:04:50.205883+0800 002-KVC取值&赋值过程[52581:1216985] 取值:name = getter: _name
3.2 成员变量获取
3.2.1 accessInstanceVariablesDirectly返回YES
- 注意:accessInstanceVariablesDirectly返回NO,直接到valueForUndefinedKey
- 访问成员变量获取顺序: _
, _is , , or is
// 1
ko->_name = @"_name";
ko->_isName = @"_isName";
ko->name = @"name";
ko->isName = @"isName";
2020-02-13 21:09:31.594596+0800 002-KVC取值&赋值过程[52624:1220018] 取值:name = _name
// 2
ko->_isName = @"_isName";
ko->name = @"name";
ko->isName = @"isName";
2020-02-13 21:22:54.308941+0800 002-KVC取值&赋值过程[52770:1229311] 取值:name = _isName
// 3
ko->name = @"name";
ko->isName = @"isName";
2020-02-13 21:23:32.312669+0800 002-KVC取值&赋值过程[52790:1230070] 取值:name = name
// 4
ko->isName = @"isName";
2020-02-13 21:24:02.391724+0800 002-KVC取值&赋值过程[52809:1230787] 取值:name = isName
3.2.2 valueForUndefinedKey
- (id)valueForUndefinedKey:(NSString *)key {
return [NSString stringWithFormat:@"%@-is-Undefined", key];
}
// 结果
2020-02-13 21:19:29.520438+0800 002-KVC取值&赋值过程[52698:1226144] 取值:name = name-is-Undefined
4 kvc的取值过程 之集合类型
- 集合类型的取值需要多实现一些方法
- countOf
,objectIn AtIndex:和 AtIndexes:
@property (nonatomic, strong) NSArray *arr;
// 增加的方法
- (NSInteger)countOfPens {
NSLog(@"%s",__func__);
return self.arr.count;
}
- (id)objectInPensAtIndex:(NSUInteger)index {
NSLog(@"%s",__func__);
return [NSString stringWithFormat:@"pens %lu", index];
}
- 试验一下
ko.arr = @[@"pen0", @"pen1"];
NSArray *array = [ko valueForKey:@"pens"];
NSLog(@"%d", array.count);
NSLog(@"%@",[array objectAtIndex:1]);
// 打印
2020-02-13 21:45:00.231940+0800 002-KVC取值&赋值过程[53098:1247507] -[KVCObject countOfPens]
2020-02-13 21:45:00.232067+0800 002-KVC取值&赋值过程[53098:1247507] 2
2020-02-13 21:45:00.232178+0800 002-KVC取值&赋值过程[53098:1247507] -[KVCObject objectInPensAtIndex:]
2020-02-13 21:45:00.232267+0800 002-KVC取值&赋值过程[53098:1247507] pens 1
5 总结
- kvc赋值
- setter方法调用,setKey,_setKey,setIsKey
- accessInstanceVariablesDirectly返回YES时进行成员变量赋值:_
, _is , , or is - setValue: forUndefinedKey:
- kvc取值,非集合类型
- getter方法查找:get
, , is , or _ - accessInstanceVariablesDirectly返回YES时进行成员变量取值:_
, _is , , or is - valueForUndefinedKey
- kvc取值,集合类型
需要多实现一些方法,类似countOf
,objectIn AtIndex:和 AtIndexes:类似这些
- 基本原理差不多就这些了,欢迎大家一起讨论! 诙谐学习,不干不燥~