3

使用此处的答案,此方法可以实现类似于 obj-c 中的 ruby​​ 映射:

- (NSArray *)mapObjectsUsingBlock:(id (^)(id obj, NSUInteger idx))block {
    NSMutableArray *result = [NSMutableArray arrayWithCapacity:[self count]];
    [self enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
        [result addObject:block(obj, idx)];
    }];
    return result;
}

我的问题是如果在应用块时发生错误,我该如何跳过一个对象?通常要跳过枚举器中的某些内容,只需使用该return命令,但这不是上述方法中的选项,因为该块预计会返回某些内容。

在此示例中,我使用return跳过但收到错误:

NSArray *mappedArray = [objArray mapObjectsUsingBlock:^(id obj, NSUInteger i) {
    // i don't want this obj to be included in final array
    // so I try to skip it
    return;   // ERROR:incompatible block pointer types sending 
              // 'void(^)(__strong id, NSUInteger)' to parameter of type 
              // 'id(^)(__strong id, NSUInteger)'


    // else do some processing
    return soupedUpObj;
}];

我目前的解决方法是简单地返回一个空对象,然后将它们从最终数组中删除。但我确信一定有比这更好的方法。

4

3 回答 3

5

如果实现类似于您在上面显示的内容,则只需将块结果应用于中间值,然后在将其添加到结果数组之前检查它是有意义的。像这样的东西:

- (NSArray *)mapObjectsUsingBlock:(id (^)(id obj, NSUInteger idx))block {
    NSMutableArray *result = [NSMutableArray arrayWithCapacity:[self count]];
    [self enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
        id blockResult = block( obj, idx );
        if( result != nil ){
          [result addObject:blockResult];
        }
    }];
    return result;
}
于 2013-08-21T15:44:18.287 回答
1

一种快速的补救措施:编写您自己的变体,它使用 NSPointerArray 而不是 NSArray。NSPointerArray 可以保持零。然后可以保留顺序,您可以使用 nil 来指示错误(假设 NSNull 是一个有效值,不能用于指示错误)。使用 NSPointerArray,你的块只会返回 nil。

于 2013-08-21T16:06:00.133 回答
0

这只是对mapObjectsUsingBlock:来自任何框架或库的限制(它不是标准的 Apple API)。

然而,实现数组映射功能并不困难,因此您可以轻松编写自己的版本来处理nil来自块参数的返回值。

于 2013-08-21T14:47:28.347 回答