Objective-c:如何完成多个异步服务调用并阻塞它们

时间:2015-05-12 12:36:46

标签: objective-c asynchronous objective-c-blocks

我有一个senario要求我多次调用web 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而不是我自己的自定义解决方案。鉴于异步服务调用使用的内部完成块,我该怎么做?

关于如何解决这个问题的任何其他建议都将受到赞赏。

2 个答案:

答案 0 :(得分:7)

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);
}];

答案 1 :(得分:1)

使用dispatch_group_t。请参阅Waiting on Groups of Queued Tasks

主题没有提及它,但使用dispatch_group_notify注册一个块而不是内联等待。