Reputation: 7249
I have a senario that requires me to make multiple call to a web api. The following is an example.
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
//...
}
I want to use the built in dispatch_queue
rather than my own custom solution here. How can I do that given the inner completion block used by the asynchronous service call?
Also any other advice on how to go about this would be appreciated.
Upvotes: 1
Views: 1524
Reputation: 7605
Use dispatch_group_t
. See Waiting on Groups of Queued Tasks.
The topic doesn't mention it, but use dispatch_group_notify
to register a block instead of waiting inline.
Upvotes: 1
Reputation: 38180
Dispatch groups have been invented for this purpose:
dispatch_group_t requestGroup = dispatch_group_create();
dispatch_group_async(requestGroup, queue, ^{
// ...
});
dispatch_group_wait(requestGroup, DISPATCH_TIME_FOREVER);
completionBlock();
Or instead of waiting:
dispatch_group_notify(requestGroup, dispatch_get_main_queue(), ^{
completionBlock();
});
Also, instead of dispatching blocks to the group, you can also enter and leave a group manually, which works well with asynchronous service APIs:
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);
}];
Upvotes: 7