定義
KVC
的全稱是Key-Value Coding
淤击,翻譯成中文是 鍵值編碼
际长,鍵值編碼是由NSKeyValueCoding
非正式協(xié)議啟用的一種機(jī)制铃剔,對(duì)象采用該協(xié)議來(lái)間接訪問(wèn)其屬性
费变。既可以通過(guò)一個(gè)字符串key來(lái)訪問(wèn)某個(gè)屬性
粥帚。這種間接訪問(wèn)機(jī)制補(bǔ)充了實(shí)例變量及其相關(guān)的訪問(wèn)器方法所提供的直接訪問(wèn)灰蛙。
KVC 相關(guān)API
常用方法
主要有以下四個(gè)常用的方法
- 通過(guò)
key
設(shè)值/取值
//直接通過(guò)Key來(lái)取值
- (nullable id)valueForKey:(NSString *)key;
//通過(guò)Key來(lái)設(shè)值
- (void)setValue:(nullable id)value forKey:(NSString *)key;
- 通過(guò)
keyPath
(即路由
)設(shè)值/取值
//通過(guò)KeyPath來(lái)取值
- (nullable id)valueForKeyPath:(NSString *)keyPath;
//通過(guò)KeyPath來(lái)設(shè)值
- (void)setValue:(nullable id)value forKeyPath:(NSString *)keyPath;
其他方法
//默認(rèn)返回YES祟剔,表示如果沒(méi)有找到Set<Key>方法的話,會(huì)按照_key缕允,_iskey峡扩,key,iskey的順序搜索成員障本,設(shè)置成NO就不這樣搜索
+ (BOOL)accessInstanceVariablesDirectly;
//KVC提供屬性值正確性驗(yàn)證的API教届,它可以用來(lái)檢查set的值是否正確、為不正確的值做一個(gè)替換值或者拒絕設(shè)置新值并返回錯(cuò)誤原因驾霜。
- (BOOL)validateValue:(inout id __nullable * __nonnull)ioValue forKey:(NSString *)inKey error:(out NSError **)outError;
//這是集合操作的API案训,里面還有一系列這樣的API,如果屬性是一個(gè)NSMutableArray粪糙,那么可以用這個(gè)方法來(lái)返回强霎。
- (NSMutableArray *)mutableArrayValueForKey:(NSString *)key;
//如果Key不存在,且KVC無(wú)法搜索到任何和Key有關(guān)的字段或者屬性蓉冈,則會(huì)調(diào)用這個(gè)方法城舞,默認(rèn)是拋出異常。
- (nullable id)valueForUndefinedKey:(NSString *)key;
//和上一個(gè)方法一樣寞酿,但這個(gè)方法是設(shè)值家夺。
- (void)setValue:(nullable id)value forUndefinedKey:(NSString *)key;
//如果你在SetValue方法時(shí)面給Value傳nil,則會(huì)調(diào)用這個(gè)方法
- (void)setNilValueForKey:(NSString *)key;
//輸入一組key,返回該組key對(duì)應(yīng)的Value伐弹,再轉(zhuǎn)成字典返回拉馋,用于將Model轉(zhuǎn)到字典。
- (NSDictionary<NSString *, id> *)dictionaryWithValuesForKeys:(NSArray<NSString *> *)keys;
KVC 設(shè)值 底層原理
在日常開(kāi)發(fā)中惨好,針對(duì)對(duì)象屬性的賦值煌茴,一般有以下兩種方式
- 直接通過(guò)
setter
方法賦值 - 通過(guò)
KVC鍵值編碼
賦值
ZGPerson *person = [[ZGPerson alloc] init];
// 1、一般setter 方法
person.name = @"張三";
// 2日川、KVC方式
[person setValue:@"李四" forKey:@"name"];
下面針對(duì)使用最多的KVC設(shè)值方法:setValue:forKey
蔓腐,來(lái)進(jìn)行其底層原理的探索。
首先進(jìn)入setValue:forKey
的聲明逗鸣,發(fā)現(xiàn)是在Foundation
框架中合住,而Foundation框架是不開(kāi)源的绰精,所以我們通過(guò)Key-Value Coding Programming Guide蘋果官方文檔來(lái)研究
KVC 設(shè)值setValue
當(dāng)調(diào)用setValue:forKey:
設(shè)置屬性value
時(shí),其底層的執(zhí)行流程為
-
【第一步】首先查找是否有這三種
setter
方法透葛,按照查找順序?yàn)?code>set<Key>:-> _set<Key> -> setIs<Key>如果
有其中任意一個(gè)
setter方法笨使,則直接設(shè)置屬性的value
(主注意:key是指成員變量名
,首字符大小寫需要符合KVC的命名規(guī)范)如果都
沒(méi)有
僚害,則進(jìn)入【第二步】
-
【第二步】:如果沒(méi)有第一步中的三個(gè)簡(jiǎn)單的setter方法硫椰,則查找
accessInstanceVariablesDirectly
是否返回YES
,-
如果返回
YES
萨蚕,則查找間接訪問(wèn)的實(shí)例變量進(jìn)行賦值靶草,查找順序?yàn)椋?code>_<key> -> _is<Key> -> <key> -> is<Key>如果找到其中任意一個(gè)實(shí)例變量,則賦值
如果都沒(méi)有岳遥,則進(jìn)入【第三步】
如果返回
NO
奕翔,則進(jìn)入【第三步】
-
【第三步】如果setter方法 或者 實(shí)例變量都沒(méi)有找到,系統(tǒng)會(huì)執(zhí)行該對(duì)象的
setValue:forUndefinedKey:
方法浩蓉,默認(rèn)拋出NSUndefinedKeyException
類型的異常
綜上所述派继,KVC通過(guò) setValue:forKey: 方法設(shè)值
的流程以設(shè)置LGPerson的對(duì)象person的屬性name為例,如下圖所示
KVC 取值 底層原理
同樣的捻艳,我們可以通過(guò)官方文檔分析KVC取值的底層原理
當(dāng)調(diào)用valueForKey:
時(shí)驾窟,其底層的執(zhí)行流程如下
-
【第一步】首先查找getter方法,按照
get<Key> -> <key> -> is<Key> -> _<key>
的方法順序查找认轨,如果
找到
绅络,則進(jìn)入【第五步】如果
沒(méi)有找到
,則進(jìn)入【第二步】
-
【第二步】如果第一步中的getter方法沒(méi)有找到嘁字,KVC會(huì)查找
countOf <Key>和objectIn <Key> AtIndex :和<key> AtIndexes :
如果找到
countOf <Key>
和其他兩個(gè)中的一個(gè)恩急,則會(huì)創(chuàng)建一個(gè)響應(yīng)所有NSArray
方法的集合代理對(duì)象
,并返回該對(duì)象纪蜒,即NSKeyValueArray
假栓,是NSArray
的子類
。代理對(duì)象隨后將接收到的所有NSArray消息轉(zhuǎn)換為countOf<Key>霍掺,objectIn<Key> AtIndex:和<key>AtIndexes:
消息的某種組合,用來(lái)創(chuàng)建鍵值編碼對(duì)象拌蜘。如果原始對(duì)象還實(shí)現(xiàn)了一個(gè)名為get<Key>:range:
之類的可選方法杆烁,則代理對(duì)象也將在適當(dāng)時(shí)使用該方法(注意:方法名的命名規(guī)則要符合KVC的標(biāo)準(zhǔn)命名方法,包括方法簽名简卧。)如果沒(méi)有找到這三個(gè)訪問(wèn)數(shù)組的兔魂,請(qǐng)繼續(xù)進(jìn)入【第三步】
-
【第三步】如果沒(méi)有找到上面的幾種方法,則會(huì)同時(shí)查找
countOf <Key>举娩,enumeratorOf<Key>和memberOf<Key>
這三個(gè)方法如果這三個(gè)方法都找到析校,則會(huì)創(chuàng)建一個(gè)響應(yīng)
所有NSSet方法的集合代理對(duì)象
构罗,并返回該對(duì)象,此代理對(duì)象隨后將其收到的所有NSSet
消息轉(zhuǎn)換為countOf<Key>智玻,enumeratorOf<Key>和memberOf<Key>:
消息的某種組合遂唧,用于創(chuàng)建它的對(duì)象如果還是沒(méi)有找到,則進(jìn)入【第四步】
-
【第四步】如果還沒(méi)有找到吊奢,檢查類方法
InstanceVariablesDirectly
是否YES
盖彭,依次搜索_<key>,_is<Key>页滚,<key>或is<Key>
的實(shí)例變量- 如果搜到召边,
直接獲取實(shí)例變量的值
,進(jìn)入【第五步】
- 如果搜到召边,
-
【第五步】根據(jù)搜索到的
屬性值的類型
裹驰,返回不同的結(jié)果如果是
對(duì)象指針
隧熙,則直接返回結(jié)果如果是
NSNumber支持
的標(biāo)量類型,則將其存儲(chǔ)在NSNumber實(shí)例
中并返回它如果是是
NSNumber不支持
的標(biāo)量類型幻林,請(qǐng)轉(zhuǎn)換為NSValue對(duì)象
并返回該對(duì)象
【第六步】如果上面5步的方法
均失敗
贞盯,系統(tǒng)會(huì)執(zhí)行該對(duì)象的valueForUndefinedKey:
方法,默認(rèn)拋出NSUndefinedKeyException
類型的異常
綜上所述滋将,KVC通過(guò) valueForKey: 方法取值
的流程以設(shè)置LGPerson
的對(duì)象person的屬性name
為例邻悬,如下圖所示
使用keyPath
在實(shí)際開(kāi)發(fā)過(guò)程中,一個(gè)類的成員變量有可能是自定義類或者其他的復(fù)雜數(shù)據(jù)類型随闽,我們可以先用KVC
獲取該屬性父丰,然后再用KVC來(lái)獲取這個(gè)自定義類的屬性。但這樣比較繁瑣掘宪,因此KVC提供了一個(gè)解決方案蛾扇,keyPath
。
// 通過(guò)KeyPath來(lái)取值
- (nullable id)valueForKeyPath:(NSString *)keyPath;
// 通過(guò)KeyPath來(lái)設(shè)值
- (void)setValue:(nullable id)value forKeyPath:(NSString *)keyPath;
下面舉個(gè)例子
@interface ZGPerson : NSObject
@property (copy, nonatomic) NSString *name;
@property (assign, nonatomic) NSInteger *sex;
@property (strong, nonatomic) NSNumber *age;
@property (strong, nonatomic) Address *address;
@end
......分割線
@interface Address : NSObject
@property (copy, nonatomic) NSString *city;
@property (copy, nonatomic) NSString *street;
@end
......分割線
- (void)viewDidLoad {
[super viewDidLoad];
ZGPerson *myself = [[ZGPerson alloc] init];
[myself setValue:@"ysy" forKey:@"name"];
NSLog(@"-------name = %@",myself.name);
NSLog(@"-------name = %@",[myself valueForKey:@"name"]);
/**
keyPath的setter方法:setValue: forKeyPath:
keyPath的getter方法:valueForKeyPath:
keyPath為多級(jí)訪問(wèn)魏滚,使用點(diǎn)語(yǔ)法
*/
//注意镀首,這里要想使用keypath對(duì)adress的屬性進(jìn)行賦值,必須先給myself賦一個(gè)Address對(duì)象
Address *myAddress = [[Address alloc] init];
[myself setValue:myAddress forKey:@"address"];
//KeyPath為多級(jí)訪問(wèn)
[myself setValue:@"shanghai" forKeyPath:@"address.city"];
NSLog(@"-------city = %@",myself.address.city);
NSLog(@"-------city = %@",[myself valueForKeyPath:@"address.city"]);
}
異常處理
使用KVC過(guò)程中最常見(jiàn)的異常就是不小心使用了錯(cuò)誤的key鼠次,或者在設(shè)值時(shí)不小心傳了nil的值更哄,KVC有特定的方法處理這些異常。
- KVC處理
nil異常
腥寇,如果在設(shè)值過(guò)程中成翩,不小心傳了nil值,KVC會(huì)調(diào)用方法setNilValueForKey:
赦役,這個(gè)默認(rèn)方法是拋出NSInvalidArgumentException
異常麻敌,所以一般而言最好重寫
這個(gè)方法,對(duì)異常進(jìn)行處理掂摔。- KVC處理
UndefinedKey
異常术羔,如果在設(shè)值取值傳的key不存在時(shí)赢赊,程序就會(huì)crash,設(shè)值會(huì)調(diào)用到setValue:forUndefinedKey:
方法级历,而取值會(huì)調(diào)用valueForUndefinedKey:
方法释移,這兩個(gè)方法默認(rèn)都是拋出NSUndefinedKeyException
異常,因此如果要避免程序crash鱼喉,可以重寫這兩個(gè)方法秀鞭。
KVC 的多值操作
批量取值操作
KVC還有更強(qiáng)大的功能,可以根據(jù)給定的一組key扛禽,獲取到一組value锋边,并且以字典的形式返回。
- (NSDictionary<NSString *, id> *)dictionaryWithValuesForKeys:(NSArray<NSString *> *)keys;
批量賦值操作
同樣编曼,也可以通過(guò)KVC進(jìn)行批量賦值豆巨。使用對(duì)象調(diào)用setValuesForKeysWithDictionary:
方法時(shí),可以傳入一個(gè)包含key掐场、value
的字典進(jìn)去往扔,KVC可以將所有數(shù)據(jù)按照屬性名和字典的key進(jìn)行匹配,并將value給User對(duì)象的屬性賦值熊户。
- (void)setValuesForKeysWithDictionary:(NSDictionary<NSString *, id> *)keyedValues;
示例
示例如下:
//批量賦值
NSDictionary *dic = @{
@"name":@"xiaoMing",
@"sex":@1,
@"age":@12,
@"address":myAddress
};
[myself setValuesForKeysWithDictionary:dic];
//批量取值
NSArray *keys = @[@"name",@"age",@"sex",@"address"];
NSDictionary *values = [myself dictionaryWithValuesForKeys:keys];
NSLog(@"%@",values);
輸出:
{
address = "<Address: 0x280d50360>";
age = 12;
name = xiaoMing;
sex = 1;
}
集合屬性操作
當(dāng)我們要操作一個(gè)對(duì)象里的集合屬性時(shí)(NSArray萍膛、NSSet等)
,我們可以通過(guò)KVC方法取到集合屬性嚷堡,然后通過(guò)集合屬性操作集合中的元素蝗罗。實(shí)際開(kāi)發(fā)中最常用的方法,叫做間接操作蝌戒。
直接操作要實(shí)現(xiàn)下面的方法串塑,但通常不會(huì)用到:
有序集合對(duì)應(yīng)方法如下:
-countOf<Key>//必須實(shí)現(xiàn),對(duì)應(yīng)于NSArray的基本方法count:2 -objectIn<Key>AtIndex:
-<key>AtIndexes://這兩個(gè)必須實(shí)現(xiàn)一個(gè)北苟,對(duì)應(yīng)于 NSArray 的方法 objectAtIndex: 和 objectsAtIndexes:
-get<Key>:range://不是必須實(shí)現(xiàn)的桩匪,但實(shí)現(xiàn)后可以提高性能,其對(duì)應(yīng)于 NSArray 方法 getObjects:range:
-insertObject:in<Key>AtIndex:
-insert<Key>:atIndexes://兩個(gè)必須實(shí)現(xiàn)一個(gè)友鼻,類似于 NSMutableArray 的方法 insertObject:atIndex: 和 insertObjects:atIndexes:
-removeObjectFrom<Key>AtIndex:
-remove<Key>AtIndexes://兩個(gè)必須實(shí)現(xiàn)一個(gè)傻昙,類似于 NSMutableArray 的方法 removeObjectAtIndex: 和 removeObjectsAtIndexes:
-replaceObjectIn<Key>AtIndex:withObject:
-replace<Key>AtIndexes:with<Key>://可選的,如果在此類操作上有性能問(wèn)題彩扔,就需要考慮實(shí)現(xiàn)之
無(wú)序集合對(duì)應(yīng)方法如下:
-countOf<Key>//必須實(shí)現(xiàn)屋匕,對(duì)應(yīng)于NSArray的基本方法count:
-objectIn<Key>AtIndex:
-<key>AtIndexes://這兩個(gè)必須實(shí)現(xiàn)一個(gè),對(duì)應(yīng)于 NSArray 的方法 objectAtIndex: 和 objectsAtIndexes:
-get<Key>:range://不是必須實(shí)現(xiàn)的借杰,但實(shí)現(xiàn)后可以提高性能,其對(duì)應(yīng)于 NSArray 方法 getObjects:range:
-insertObject:in<Key>AtIndex:
-insert<Key>:atIndexes://兩個(gè)必須實(shí)現(xiàn)一個(gè)进泼,類似于 NSMutableArray 的方法 insertObject:atIndex: 和 insertObjects:atIndexes:
-removeObjectFrom<Key>AtIndex:
-remove<Key>AtIndexes://兩個(gè)必須實(shí)現(xiàn)一個(gè)蔗衡,類似于 NSMutableArray 的方法 removeObjectAtIndex: 和 removeObjectsAtIndexes:
-replaceObjectIn<Key>AtIndex:withObject:
-replace<Key>AtIndexes:with<Key>://這兩個(gè)都是可選的纤虽,如果在此類操作上有性能問(wèn)題,就需要考慮實(shí)現(xiàn)之
使用 KVC 進(jìn)行集合類的運(yùn)算
KVC 提供的valueForKeyPath:
方法非常強(qiáng)大绞惦,可以在keyPath中嵌套集合運(yùn)算符對(duì)集合中的對(duì)象進(jìn)行相關(guān)的運(yùn)算逼纸,例如求一個(gè)數(shù)組中所有Person對(duì)象的age總和。集合對(duì)象主要指NSArray和NSSet
济蝉,不包括NSDictionary
杰刽。
集合運(yùn)算符的格式
keyPathToCollection.@collentionOperator.keyPathToproperty
-
keyPathToCollection
:Left key path,要操作的集合對(duì)象王滤,若調(diào)用 valueForKeyPath: 方法的對(duì)象本來(lái)就是集合對(duì)象贺嫂,則可以省略; -
collentionOperator
:Collection operator雁乡,集合操作符第喳,一般以@開(kāi)頭; -
keyPathToproperty
:Right key path踱稍,要運(yùn)算的屬性曲饱。
舉例
Address *myAddress = [[Address alloc] init];
//
[myself setValue:myAddress forKey:@"address"];
//KeyPath為多級(jí)訪問(wèn)
[myself setValue:@"shanghai" forKeyPath:@"address.city"];
NSLog(@"-------city = %@",myself.address.city);
NSLog(@"-------city = %@",[myself valueForKeyPath:@"address.city"]);
NSMutableArray *array = [NSMutableArray array];
for ( int i = 0 ; i < 5 ; i++ ) {
Address *address = [[Address alloc] init];
NSString *cityStr = [NSString stringWithFormat:@"city-%d",i];
//批量賦值
NSDictionary *dic = @{
@"city":cityStr,
@"street":@"street",
@"cityNumber":@(i),
@"streetNumber":@(100+i)
};
[address setValuesForKeysWithDictionary:dic];
[array addObject:address];
}
//返回?cái)?shù)組中保存的對(duì)象的屬性,返回值為數(shù)組
NSArray *cityArray = [array valueForKeyPath:@"cityNumber"];
NSLog(@"%@",cityArray);
NSArray *streetNumberArray = [array valueForKeyPath:@"streetNumber"];
//求平均值
NSNumber *avg = [array valueForKeyPath:@"@avg.streetNumber"];
NSLog(@"%@-%@",streetNumberArray,avg);
打印輸出:
-------city = shanghai
2021-01-18 16:28:30.373550+0800 005---Runtime應(yīng)用[73332:21674820] -------city = shanghai
2021-01-18 16:28:30.373673+0800 005---Runtime應(yīng)用[73332:21674820] (
0,
1,
2,
3,
4
)
2021-01-18 16:28:30.373814+0800 005---Runtime應(yīng)用[73332:21674820] (
100,
101,
102,
103,
104
)-102
集合運(yùn)算符的分類
集合運(yùn)算符主要分為三類:
- 集合操作符:處理集合包含的對(duì)象珠月,并根據(jù)操作符的不同返回不同的類型扩淀,返回值以NSNumber為主。
- 數(shù)組操作符:根據(jù)操作符的條件啤挎,將符合條件的對(duì)象包含在數(shù)組中返回驻谆。
- 嵌套操作符:處理集合對(duì)象中嵌套其他集合對(duì)象的情況,返回結(jié)果也是一個(gè)集合對(duì)象侵浸。
1. 集合操作符
集合操作符處理 NSArray和 NSSet
及其子類這樣的集合對(duì)象旺韭,并根據(jù)不同的操作符返回不同類型的對(duì)象,返回值一般都是NSNumber
掏觉。
主要有以下幾種
-
@avg
用來(lái)計(jì)算集合中 right keyPath 指定的屬性的平均值区端。
//@avg:平均值
NSNumber *avg = [array valueForKeyPath:@"@avg.streetNumber"];
NSLog(@"%@",avg); -
@count
用來(lái)計(jì)算集合中對(duì)象的數(shù)量。備注:@count 操作符比較特殊澳腹,它不需要寫 right keyPath织盼,即使寫了也會(huì)被忽略。
//@count:集合里對(duì)象的數(shù)量
NSNumber *count = [array valueForKeyPath:@"@count"];
NSLog(@"%@",count); -
@sum
用來(lái)計(jì)算集合中 right keyPath 指定的屬性的總和酱塔。
//@sum:總和
NSNumber *sum = [array valueForKeyPath:@"@sum.streetNumber"];
NSLog(@"%@",sum); -
@max
用來(lái)查找集合中 right keyPath 指定的屬性的最大值沥邻。
//@max:最大值
NSNumber *max = [array valueForKeyPath:@"@max.cityNumber"];
NSLog(@"%@",max); -
@min
用來(lái)查找集合中 right keyPath 指定的屬性的最小值。
//@min:最小值
NSNumber *min = [array valueForKeyPath:@"@min.cityNumber"];
NSLog(@"%@",min);
備注:
@max 和 @min
在進(jìn)行判斷時(shí)羊娃,都是通過(guò)調(diào)用compare:
方法進(jìn)行判斷唐全,所以可以通過(guò)重寫該方法對(duì)判斷過(guò)程進(jìn)行控制。
加上一些打印
NSArray *streetNumberArray = [array valueForKeyPath:@"streetNumber"];
NSNumber *avg = [array valueForKeyPath:@"@avg.streetNumber"];
NSNumber *count = [array valueForKeyPath:@"@count"];
NSNumber *sum = [array valueForKeyPath:@"@sum.streetNumber"];
NSNumber *max = [array valueForKeyPath:@"@max.cityNumber"];
NSNumber *min = [array valueForKeyPath:@"@min.cityNumber"];
輸出:
2021-01-18 16:39:08.167698+0800 005---Runtime應(yīng)用[73377:21677966] (
100,
101,
102,
103,
104
)-avg:102
count:5
sum:510
max:4
min:0
2. 數(shù)組操作符(因?yàn)榉祷氐氖菙?shù)組,所以叫數(shù)組操作符)
-
@unionOfObjects
將集合中的所有對(duì)象的同一個(gè)屬性放在數(shù)組中返回邮利。這個(gè)和直接寫屬性好像沒(méi)區(qū)別弥雹。
NSArray *city = [array valueForKeyPath:@"@unionOfObjects.city"];
NSLog(@"%@",city);
NSArray *cityArray = [array valueForKeyPath:@"city"];
NSLog(@"%@",cityArray);
-
@distinctUnionOfObjects
將集合中對(duì)象的屬性進(jìn)行去重并返回。
NSArray *streetNumberArr = [array valueForKeyPath:@"@distinctUnionOfObjects.streetNumber"];
NSLog(@"%@",streetNumberArr);
NSArray *city = [array valueForKeyPath:@"@unionOfObjects.city"];
NSLog(@"%@",city);
NSArray *street= [array valueForKeyPath:@"@distinctUnionOfObjects.street"];
NSLog(@"%@",street);
打印結(jié)果:
2021-01-18 16:44:22.055668+0800 005---KVC[73410:21680170] (
street
)
2021-01-18 16:44:22.055726+0800 005---KVC[73410:21680170] (
"city-0",
"city-1",
"city-2",
"city-3",
"city-4"
)
3. 嵌套操作符
嵌套操作符是對(duì)集合里的集合進(jìn)行操作延届,比如數(shù)組里面的數(shù)組剪勿。
NSMutableArray *array1 = [NSMutableArray array];
for ( int i = 0 ; i < 5 ; i++ ) {
Address *address = [[Address alloc] init];
NSString *cityStr = [NSString stringWithFormat:@"city-%d",i];
//批量賦值
NSDictionary *dic = @{
@"city":cityStr,
@"street":@"street",
@"cityNumber":@(i),
@"streetNumber":@(100+i)
};
[address setValuesForKeysWithDictionary:dic];
[array1 addObject:address];
}
NSMutableArray *array2 = [NSMutableArray array];
for ( int i = 3 ; i < 9 ; i++ ) {
Address *address = [[Address alloc] init];
NSString *cityStr = [NSString stringWithFormat:@"city-%d",i];
//批量賦值
NSDictionary *dic = @{
@"city":cityStr,
@"street":@"street",
@"cityNumber":@(i),
@"streetNumber":@(100+i)
};
[address setValuesForKeysWithDictionary:dic];
[array2 addObject:address];
}
NSArray *array = @[array1,array2];
NSArray *cityArray = [array valueForKeyPath:@"city"];
NSArray *result = [array valueForKeyPath:@"@unionOfArrays.city"];
NSArray *disResult = [array valueForKeyPath:@"@distinctUnionOfArrays.city"];
NSSet *resultSet = [array valueForKeyPath:@"@distinctUnionOfSets.city"];
NSLog(@"%@",cityArray);
NSLog(@"%@",result);
NSLog(@"%@",disResult);
NSLog(@"%@",resultSet);
@unionOfArrays
是用來(lái)操作集合內(nèi)部的集合,將所有right keyPath對(duì)應(yīng)的屬性放在一個(gè)數(shù)組中返回方庭。
NSArray *result = [array valueForKeyPath:@"@unionOfArrays.city"];@distinctUnionOfArrays
是用來(lái)操作集合內(nèi)部的集合對(duì)象厕吉,將所有right keyPath對(duì)應(yīng)的對(duì)象放在一個(gè)數(shù)組中,并進(jìn)行排重械念。
NSArray *result = [array valueForKeyPath:@"@distinctUnionOfArrays.city"];@distinctUnionOfSets
是用來(lái)操作集合內(nèi)部的集合對(duì)象头朱,將所有right keyPath對(duì)應(yīng)的對(duì)象放在一個(gè)set中,并進(jìn)行排重订讼。
NSSet *result = [array valueForKeyPath:@"@distinctUnionOfSets.city"];
KVC性能
根據(jù)上面KVC的實(shí)現(xiàn)原理髓窜,我們可以看出KVC的性能并不如直接訪問(wèn)屬性快,雖然這個(gè)性能消耗是微乎其微的欺殿。所以在使用KVC的時(shí)候寄纵,建議最好不要手動(dòng)設(shè)置屬性的setter、getter
脖苏,這樣會(huì)導(dǎo)致搜索步驟變長(zhǎng)程拭。
而且盡量不要用KVC進(jìn)行集合操作,例如NSArray棍潘、NSSet之類的恃鞋,集合操作的性能消耗更大,而且還會(huì)創(chuàng)建不必要的對(duì)象亦歉。