假设我有一个数组数组,如:
NSArray *array = @[@[@1, @2], @[@3, @4], @[@5, @6]];
是否有一个KVC密钥路径可以给我@ [@ 1,@ 3,@ 5]?
答案 0 :(得分:2)
令我惊讶的是,虽然它依赖于一些无证的行为。
NSArray
覆盖-valueForKey:
的文档说它通过使用提供的密钥将-valueForKey:
应用于每个元素并返回它来构建一个新数组。 不表示任何密钥都是特殊的。
但是,NSDictionary
的覆盖确实表示以@
开头的密钥是专门处理的。它不是查看字典的内容,而是查看字典本身的属性,以匹配前导@
的剥离键。因此,您可以使用[someDict valueForKey:@"@count"]
来获取字典中对象的数量。
事实证明,NSArray
实际上尊重相同的惯例。您可以使用[array valueForKey:@"@firstObject"]
在示例中获取@[@[@1, @2]]
。现在的问题是,如何应用于内部数组,而不是外部数组。
首先,如果您只是在密钥上没有[array valueForKey:@"firstObject"]
的情况下致电@
会怎样?外部数组在每个内部数组上调用[innerArray valueForKey:@"firstObject"]
。反过来,每个内部数组都试图在每个元素上调用[element valueForKey:@"firstObject"]
。但是,它的元素是NSNumber
个对象,它们与键“firstObject”不符合KVC。所以这会爆发。
但是,KVC支持collection operators -valueForKeyPath:
(注意结尾处的“路径”)。一个运算符是@unionOfObjects
。这将操作符右侧的路径部分应用于数组的元素,然后返回结果数组。这类似于-valueForKey:
传播到内部数组的情况,除了您为内部数组指定不同的键。
因此,结合这些机制,您可以:[array valueForKeyPath:@"@unionOfObjects.@firstObject"]
获取@[@1, @3, @5]
。外部数组将[innerArray valueForKeyPath:@"@firstObject"]
应用于每个内部数组。由于前导@
,它不会传播到内部数组的元素。它只获取内部数组的firstObject
。然后外部数组将这些数组合成一个结果数组。
答案 1 :(得分:0)
KVC密钥路径仅在对象为confirming Key Value coding compliance时才起作用。表示对象,缩放器值应该具有沿着键名称的setter和getter。在您的结构中,没有用于具有getter和setter的索引路径的键。所以我创建了自定义getter方法来满足内部对象索引路径的NSKeyValueCoding。这将适用于内部数组的每个索引。
@interface NSArray (KVO)
- (id) unionOfObjectsForKeyPath:(NSString*)keyPath;
@end
@implementation NSArray (KVO)
- (id) unionOfObjectsForKeyPath:(NSString*)keyPath
{
NSMutableArray * values = [NSMutableArray new];
for (id obj in self) {
if ([obj isKindOfClass:[NSArray class]]) {
@try {
NSUInteger index = [keyPath integerValue];
id value = nil;
if (index < [(NSArray *)obj count]) {
value = [obj objectAtIndex:index];
if(value && value!=[NSNull null] )
{
[values addObject:value];
}
}
}
@catch (id) {}
}
}
return [NSArray arrayWithArray:values];
}
@end
在VC中:
self.myArray = @[@[@1, @2], @[@3, @4], @[@5, @6]];
NSArray *testArray =[self.myArray unionOfObjectsForKeyPath:@"0"];
NSLog(@"test array : %@", testArray);