1.kvc:Key-Value Coding
- 基本類型使用
- (void)setValue:(nullable id)value forKey:(NSString *)key;
- (nullable id)valueForKey:(NSString *)key;
- 集合類型使用
@property (nonatomic, strong) NSArray *array;
// 修改不可變數(shù)組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
)
- 非對象類型,轉(zhuǎn)換成相應(yīng)的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);
// 創(chuàng)建一個同類型結(jié)構(gòu)體用來接收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
- 官方文檔

image.png
1.進(jìn)行setter方法查找,
2.進(jìn)行成員變量查找,
3.未找到則調(diào)用setValue:forUndefinedKey
準(zhǔn)備測試類驗證
@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<Key> or _set<Key> 調(diào)用
會依次調(diào)用setKey,_setKey,setIsKey這三種方法
不會調(diào)用_setIsKey,此方法不被調(diào)用
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 成員變量賦值順序
當(dāng)2.1尋找未果,并且accessInstanceVariablesDirectly返回YES的時候,會進(jìn)行成員變量查找,如果返回NO,則跳過該步驟,直接到最后一步setValue: forUndefinedKey:
驗證代碼
NSLog(@"_name = %@",ko->_name);
NSLog(@"_isName = %@",ko->_isName);
NSLog(@"name = %@",ko->name);
NSLog(@"isName = %@",ko->isName);
2.2.1 當(dāng)accessInstanceVariablesDirectly返回NO
+ (BOOL)accessInstanceVariablesDirectly {
return NO;
}
- 結(jié)果如下,所有成員變量均未被賦值
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 當(dāng)accessInstanceVariablesDirectly返回YES
- 開始查找成員變量
- 順序: _<key>, _is<Key>, <key>, or is<Key>
// 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方法查找
- 調(diào)用順序: get<Key>, <key>, is<Key>, or _<key>
- 驗證
// getter方法
- (NSString *)getName{
return @"getter: getName";
}
- (NSString *)name{
return @"getter: name";
}
- (NSString *)isName{
return @"getter: isName";
}
- (NSString *)_name{
return @"getter: _name";
}
- 結(jié)果
// 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
- 訪問成員變量獲取順序: _<key>, _is<Key>, <key>, or is<Key>
// 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];
}
// 結(jié)果
2020-02-13 21:19:29.520438+0800 002-KVC取值&賦值過程[52698:1226144] 取值:name = name-is-Undefined
4 kvc的取值過程 之集合類型
- 集合類型的取值需要多實現(xiàn)一些方法
- countOf<Key>,objectIn<Key>AtIndex:和<key>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 總結(jié)
- kvc賦值
- setter方法調(diào)用,setKey,_setKey,setIsKey
- accessInstanceVariablesDirectly返回YES時進(jìn)行成員變量賦值:_<key>, _is<Key>, <key>, or is<Key>
- setValue: forUndefinedKey:
- kvc取值,非集合類型
- getter方法查找:get<Key>, <key>, is<Key>, or _<key>
- accessInstanceVariablesDirectly返回YES時進(jìn)行成員變量取值:_<key>, _is<Key>, <key>, or is<Key>
- valueForUndefinedKey
- kvc取值,集合類型
需要多實現(xiàn)一些方法,類似countOf<Key>,objectIn<Key>AtIndex:和<key>AtIndexes:類似這些
- 基本原理差不多就這些了,歡迎大家一起討論! 詼諧學(xué)習(xí),不干不燥~