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

Jos*_*ane 1 for-loop objective-c callback

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

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

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

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

谢谢.

dan*_*anh 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];
    }];
}
Run Code Online (Sandbox Code Playgroud)

这适用于短阵列.让我知道数组是否很大(数千个元素),我可以告诉你如何以不会结束堆栈的方式递归(通过使doThing方法采用单个参数并使用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}];
}
Run Code Online (Sandbox Code Playgroud)