欢迎到个人博客: liumh.com查看本文。
本文为原创,未经允许勿转载
进一步阅读之前,可以先思考这个问题: 存在数组 @[@(90), @(31), @(65), @(78), @(76)]
,如何取出数组中的最大值或者最小值?
KVC 的集合操作符可使用键路径和操作运算作用于集合中的所有元素。本文将描述一些可用的集合操作。
KVC 的集合操作符实际上就是一些特殊的键路径,以参数的形式传递给 valueForKeyPath: 方法。集合操作是以 @ 开始的字符串, 也可理解为: KVC集合操作符允许在 valueForKeyPath:
方法中使用 key path 符号在一个集合中执行方法。无论什么时候你在 key path 中看见了@,它都代表了一个特定的集合方法,其结果可以被返回或者链接,就像其他的 key path 一样。下图就是集合操作符的格式:
其中左边的键路径(keypathToCollection)指定了相对消息接收者的 NSArray 或者 NSSet,右边的键路径(keypathToProperty)指定了相对于集合内对象的键路径,集合操作作用于该键路径。
除了 @count
外的所有集合操作,都要求在集合操作右边有一键路径(keypathToProperty)。
集合操作返回的对象值决定于集合操作的类型:
以下示例会用到一些数据,先看看示例数据。想象一个 Product 类和由 Product 类对象所组成的 products 数组:
@interface Product : NSObject
@property NSString *name;
@property CGFloat price;
@property NSDate *launchedOn;
@end
键-值 编码会在必要的时候把基本数据类型的数据自动装箱和拆箱到 NSNumber 或者 NSValue 中来确保一切工作正常。
products 数组中 Product 类对象所使用数据如下:
Name | Price | Launch Date |
---|---|---|
iPhone5 | $199 | September 21, 2012 |
iPhone5 | $199 | September 21, 2012 |
iPhone5 | $199 | September 21, 2012 |
iPad Mini | $329 | November 2, 2012 |
MacBook Pro | $1699 | June 11,2012 |
MacBook Pro | $1699 | June 11,2012 |
iMac | $1299 | November 2, 2012 |
还有另一个数组 products2,它内部元素也是 Product 类对象,数据如下:
Name | Price | Launch Date |
---|---|---|
iPhone5 | $199 | September 21, 2012 |
iPad Mini | $329 | November 2, 2012 |
MacBook Pro | $1699 | June 11,2012 |
iMac | $1299 | November 2, 2012 |
iMac | $1299 | November 2, 2012 |
iMac | $1299 | November 2, 2012 |
简单集合操作符作用于 array 或者 set 中相对于集合操作符右侧的属性。包括 @avg
, @count
, @max
, @min
, @sum
.
compare:
方法决定,因此参加比较的对象必须支持和另一个对象的比较。如果右侧键路径所指对象值为 nil, 则忽略,不影响比较结果。[products valueForKeyPath:@"@count"]; // 7
[products valueForKeyPath:@"@sum.price"]; // 5632.00
[products valueForKeyPath:@"@avg.price"]; // 804.5714285714286
[products valueForKeyPath:@"@max.price"]; // 1699.00
[products valueForKeyPath:@"@min.launchedOn"]; // June 11, 2012
Pro提示:你可以简单的通过把 self 作为操作符后面的 key path 来获取一个由 NSNumber 组成的数组或者集合的总值,例如对于数组 @[@(1), @(2), @(3)] 可使用
valueForKeyPath:@"@max.self"
来获取最大值。
对象操作符包括 @distinctUnionOfObjects
和 @unionOfObjects
, 返回一个由操作符右边的 key path 所指定的对象属性组成的数组。其中 @distinctUnionOfObjects
会对数组去重,而 @unionOfObjects
不会。
NSArray *unionOfObjects = [products valueForKeyPath:@"@unionOfObjects.name"]; // 1.
NSArray *distinctUnionObjects = [products valueForKeyPath:@"@distinctUnionOfObjects.name"]; //2.
unionOfObjects 中会包含 “iPhone5”, “iPhone5”,”iPhone5”, “iPad Mini”, “MacBook Pro”, “MacBook Pro”, “iMac”
distinctUnionObjects 中会包含 “iPhone5”, “iPad Mini”, “MacBook Pro”, “iMac”, 相当于对 unionOfObjects 数组进行去重处理。
数组和集合操作符作用对象是嵌套的集合,也就是说,是一个集合且其内部每个元素是一个集合。数组和集合操作符包括 @distinctUnionOfArrays
,@unionOfArrays
,@distinctUnionOfSets
:
假定有个 totalProducts 数组,其包含两个数组 products 和 products2,以下代码片段展示了 totalProducts 的创建。
totalProducts = [NSMutableArray array];
[totalProducts addObject:products];
[totalProducts addObject:products2];
其中 products 和 products2 中元素都是 Product 类对象,其内部数据使用的是示例数据的数据内容。
对于以下操作:
NSArray *distinctUnionOfArrays = [totalProducts valueForKeyPath:@"@distinctUnionOfArrays.name"];
NSArray *unionOfArrays = [totalProducts valueForKeyPath:@"@unionOfArrays.name"];
那么 unionOfArrays 中包含 “iPhone5”, “iPhone5”, “iPhone5”, “iPad Mini”, “MacBook Pro”, “MacBook Pro”, “iMac”, “iPhone5”, “iPad Mini”, “MacBook Pro”, “iMac”, “iMac”, “iMac” 共 13 个元素。而 distinctUnionOfArrays 中仅包含 “iPhone5”, “iPad Mini”, “MacBook Pro”, “iMac” 共 4 个元素。
注意: 如果操作符右侧 key path 指定的对象为 nil,那么返回的数组中会包含 NSNull 对象.
参考:
如果觉得本文对你有帮助,就请用微信打赏我吧^_^