Objective-c: 如何进行多个异步服务调用并阻塞直到它们全部完成

Objective-c: How to make multiple async service calls and block until they are all complete

我有一个场景需要我多次调用网络 api。下面是一个例子。

getDataAsync:(NSDictionary *)dictionary withCompletion: (void (^)(NSDictionary*))completion {

    __block int counter = n; // the number of async blocks
    __block NSMutableDictionary *output = [[NSMutableDictionary alloc] init];
    void (^returnBlock)(void) = ^{
        counter--;
        if(counter != 0) return;
        completion(@{@"return": output});
        return;
    };
    void (^getResourceA)(void) = ^{
        [service getResourceA : dictionary[@"idA"] completion:
        ^(ServiceResult results, MyResourceA *a, NSString *errMsg) {
            [output setValue:a.value forKey:a.name];
            returnBlock(); 
        }];
    };
    // followed by n-1 other blocks like getResourceA
    //... 
}

我想在这里使用内置的 dispatch_queue 而不是我自己的自定义解决方案。给定异步服务调用使用的内部完成块,我该怎么做?

如果有任何其他关于如何解决此问题的建议,我们将不胜感激。

使用dispatch_group_t。参见 Waiting on Groups of Queued Tasks

题目中没有提到,而是使用dispatch_group_notify注册一个块而不是等待内联。

Dispatch groups 是为此目的发明的:

dispatch_group_t requestGroup = dispatch_group_create();
dispatch_group_async(requestGroup, queue, ^{
    // ...
});
dispatch_group_wait(requestGroup, DISPATCH_TIME_FOREVER);
completionBlock();

或者不用等待:

dispatch_group_notify(requestGroup, dispatch_get_main_queue(), ^{
    completionBlock();
});

此外,您还可以手动进入和离开群组,而不是向群组发送块,这与异步服务 API 配合得很好:

dispatch_group_enter(requestGroup);
[service getResourceA : dictionary[@"idA"] completion: ^(ServiceResult results, MyResourceA *a, NSString *errMsg) {
    [output setValue:a.value forKey:a.name];
    dispatch_group_leave(requestGroup);
}];