有没有办法用KVC获取数组数组的所有第一个对象?

时间:2016-10-28 04:43:25

标签: objective-c kvc

假设我有一个数组数组,如:

NSArray *array = @[@[@1, @2], @[@3, @4], @[@5, @6]];

是否有一个KVC密钥路径可以给我@ [@ 1,@ 3,@ 5]?

2 个答案:

答案 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);