KVC的keyPath中的集合运算符的使用

楔子

给我这个列表里面所有员工的平均薪酬。通常可能会这样写

double totalSalary = 0.0;
for (Employee *employee in employees) { 
    totalSalary += [employee.salary doubleValue];
}
double averageSalary = totalSalary / [employees count];

但是KVC提供了一种更加简洁的方法,那就是使用集合运算符,easy

[employees valueForKeyPath:@"@avg.salary"];

正文

KVC集合运算符允许在valueForKeyPath:方法中使用key path符号在一个集合中执行方法。无论什么时候你在key path中看见了@,它都代表了一个特定的集合方法,其结果可以被返回或者链接,就像其他的key path一样。

集合运算符会根据其返回值的不同分为以下三种类型:

  • 简单的集合运算符 返回的是strings, number, 或者 dates
  • 对象运算符 返回的是一个数组
  • 数组和集合运算符 返回的是一个数组或者集合

示例

下面为一个Prduct类


KVC的keyPath中的集合运算符的使用_第1张图片
@interface Product : NSObject
@property NSString *name;
@property double price;
@property NSDate *launchedOn;
@end
简单集合操作符
  • @count:返回一个值为集合中对象总数的NSNumber对象。
  • @sum:首先把集合中的每个对象都转换为double类型,然后计算其总,最后返回一个值为这个总和的NSNumber对象。
  • @avg:首先把集合中的每个对象都转换为double类型,然后计算其平均值,最后返回一个值为该平均值的NSNumber对象。
  • @max:使用compare:方法来确定最大值。所以为了让其正常工作,集合中所有的对象都必须支持和另一个对象的比较。
  • @min:和@max一样,但是返回的是集合中的最小值。
    代码如下
[products valueForKeyPath:@"@count"]; // 4
[products valueForKeyPath:@"@sum.price"]; // 3526.00
[products valueForKeyPath:@"@avg.price"]; // 881.50
[products valueForKeyPath:@"@max.price"]; // 1699.00
[products valueForKeyPath:@"@min.launchedOn"]; // June 11, 2012
对象操作符

现在有一个数组

NSArray *inventory = @[iPhone5, iPhone5, iPhone5, iPadMini, macBookPro, macBookPro];

@unionOfObjects/ @distinctUnionOfObjects: 返回一个由操作符右边的key path所指定的对象属性组成的数组。其中@distinctUnionOfObjects会对数组去重, 而@unionOfObjects不会。

[inventory valueForKeyPath:@"@unionOfObjects.name"]; // "iPhone 5", "iPhone 5", "iPhone 5", "iPad Mini", "MacBook Pro", "MacBook Pro"
[inventory valueForKeyPath:@"@distinctUnionOfObjects.name"]; // "iPhone 5", "iPad Mini", "MacBook Pro"
数组和集合操作符

数组和集合操作符跟对象操作符很相似,只不过它是在NSArray和NSSet所组成的集合中工作的。如果我们做一些例如:比较几个商店中的库存(和我们上一节类似的appleStore库存和买iPhone 5和iPad Mini的versizonStore库存)这样的工作,这个就会很有用。

  • @distinctUnionOfArrays/@unionOfArrays: 返回了一个数组,其中包含这个集合中每个数组对于这个操作符右面指定的key path进行操作之后的值。正如你期望的,distinct版本会移除重复的值。
  • @distinctUnionOfSets:和@distinctUnionOfArrays差不多, 但是它期望的是一个包含着NSSet对象的NSSet,并且会返回一个NSSet对象。因为集合不能包含重复的值,所以它只有distinct操作。
[@[appleStoreInventory, verizonStoreInventory] valueForKeyPath:@"@distinctUnionOfArrays.name"]; // "iPhone 5", "iPad Mini", "MacBook Pro"

写在后面

目前还不能自定义集合操作符。

参考文章
苹果官方文档Key-Value Coding Programming Guide
KVC Collection Operators

你可能感兴趣的:(KVC的keyPath中的集合运算符的使用)