如何在obj-c的类似ruby的Map方法中迭代时跳过对象



使用这里的答案,该方法实现了类似于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;
}];

我目前的处理方法是简单地返回一个null对象,然后从最终数组中删除它们。但我相信肯定有更好的方法。

如果实现与上面显示的类似,那么将块结果应用于中间值,然后在将其添加到结果数组之前进行检查是有意义的。类似这样的东西:

- (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;
}

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

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

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

最新更新