在下一个循环之前等待For循环中的回调

时间:2014-11-08 16:40:40

标签: objective-c for-loop callback

我有一个中等简单的for循环,看起来像这样:

for (NSObject *obj in objectsArray)
{
    [DoThingToObject:obj complete:^{
        //Do more
    }];
}

我需要在数组中的每个对象上做一件事。但是,在我开始循环并在第二个对象上执行操作之前,我需要等待第一个对象上的完成回调。

我怎样才能简单地等待,然后在循环中做下一个对象?

感谢。

1 个答案:

答案 0 :(得分:5)

如果客观c有承诺会很好,但在那之前,我通常使用递归来处理这样的事情,使用输入数组作为待办事项列表......

- (void)doThingToArray:(NSArray *)array then:(void (^)(void))completion {

    NSInteger count = array.count;
    // bonus feature: this recursive method calls its block when all things are done
    if (!count) return completion();

    id firstThing = array[0];
    // this is your original method here...
    [self doThingToObject:firstThing complete:^{
        NSArray *remainingThings = [array subarrayWithRange:NSMakeRange(1, count-1)];
        [self doThingToArray:remainingThings then:completion];
    }];
}

这适用于短阵列。让我知道数组是否很大(数千个元素),我可以告诉你如何以不会结束堆栈的方式递归(通过使doThing方法采用单个参数并“递归” with performSelector)。

编辑 - 执行选择器让当前的运行循环完成并将下一个选择器排队。当你在一个长数组上进行递归时,这可以节省堆栈,但它只需要一个参数,所以我们必须通过将数组和块参数合并到一个集合对象中来使方法的可读性稍差......

- (void)doThingToArray2:(NSDictionary *)params {

    NSArray *array = params[@"array"];
    void (^completion)(void) = params[@"completion"];

    NSInteger count = array.count;
    // bonus feature: this recursive method calls its block when all things are done
    if (!count) return completion();

    id firstThing = array[0];
    // this is your original method here...
    [self doThingToObject:firstThing complete:^{
        NSArray *remainingThings = [array subarrayWithRange:NSMakeRange(1, count-1)];
        [self performSelector:@selector(doThingToArray2:)
                   withObject:@{@"array": remainingThings, @"completion": completion}
                   afterDelay:0];
    }];
}

// call it like this:
NSArray *array = @[@1, @2, @3];
void (^completion)(void) = ^void(void) { NSLog(@"done"); };
[self doThingToArray2:@{@"array": array, @"completion": completion}];

// or wrap it in the original method, so callers don't have to fuss with the 
// single dictionary param
- (void)doThingToArray:(NSArray *)array then:(void (^)(void))completion {
    [self doThingToArray2:@{@"array": array, @"completion": completion}];
}