dispatch_group_notify does not wait for one dispatch_group_async
asynchronous, grand-central-dispatch, ios, objective-c-blocks, queue
Solution
This is because your `getPath` method runs asynchronously. You need it to not leave the group until that completion block runs. So rather than than doing `dispatch_group_async`, you should manually `dispatch_group_enter` and `dispatch_group_leave`.
You can change your code from:
dispatch_group_async(taskGroup, mainQueue, ^{
[[MDAddressManager instance] searchForPlacesContainingText:query
location:alocation
completion:^(NSArray* addresses, MDError *error){
//remoteAddresses is set
}];
});
To:
dispatch_group_enter(taskGroup);
[[MDAddressManager instance] searchForPlacesContainingText:query
location:alocation
completion:^(NSArray* addresses, MDError *error){
//remoteAddresses is set
dispatch_group_leave(taskGroup);
});
That will ensure that you don't leave the group until the completion block is called.
Alternatively, you could change `searchForPlacesContainingText` to use `dispatch_group_t` parameter:
- (void)searchForPlacesContainingText:(NSString *)searchText
location:(CLLocation *)alocation
group:(dispatch_group_t)group
completion:(MDAddressManagerBlock)completionBlock
{
dispatch_group_enter(group);
NSDictionary *parameters = [[NSMutableDictionary alloc] init];
[parameters setValue:searchText forKey:@"input"];
[[MDHTTPClient sharedHTTPClient] getPath:@"v1/remotePlaces.json"
parameters:parameters
success:^(AFHTTPRequestOperation *operation, id dict) {
if ([MDHTTPClient isResponseValid:dict])
{
completionBlock(returnArray, nil);
}
else
{
completionBlock(nil, nil);
}
dispatch_group_leave(group);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
EDLog(@"%@", error);
completionBlock(nil, [MDError errorAFNetworking:error]);
dispatch_group_leave(group);
}];
}
and change your invocation so that it doesn't do `dispatch_group_async`, but rather just passes the `taskGroup` parameter:
[[MDAddressManager instance] searchForPlacesContainingText:query
location:alocation
group:taskGroup
completion:^(NSArray* addresses, MDError *error) {
//remoteAddresses is set
});
Problem
Two concurrent background tasks need to patch two separate arrays which need to be merged in a dispatch_group_notify block.The problem is that.the first block is exceeded but the dispatch_group_notify is exceeded without waiting for the execution of the second background task. The only different between them is that the first one make a local search and the second one makes a remote call to a web service.Any clue why the second one is jumped over ? Edit: I also tried the approach mentioned in https://stackoverflow.com/a/19580584/859742 using dispatch_barrier_async but still same. ``` dispatch_group_t taskGroup = dispatch_group_create(); dispatch_queue_t mainQueue = dispatch_get_main_queue(); __block NSArray *localAddresses; __block NSArray *remoteAddresses; //Get local array in the background dispatch_group_async(taskGroup, mainQueue, ^{ //localAddresses is set }); //get remote array from server dispatch_group_async(taskGroup, mainQueue, ^{ [[MDAddressManager instance] searchForPlacesContainingText:query location:alocation completion:^(NSArray* addresses, MDError *error){ //remoteAddresses is set }); //Merge two arrays dispatch_group_notify(taskGroup, mainQueue, ^{ //remoteAddresses and local addresses are merged }); ``` And the remote search method looks like this ``` - (void)searchForPlacesContainingText:(NSString *)searchText location:(CLLocation *)alocation completion:(MDAddressManagerBlock)completionBlock { NSDictionary *parameters = [[NSMutableDictionary alloc] init]; [parameters setValue:searchText forKey:@"input"]; [[MDHTTPClient sharedHTTPClient] getPath:@"v1/remotePlaces.json" parameters:parameters success:^(AFHTTPRequestOperation *operation, id dict) { if ([MDHTTPClient isResponseValid:dict]) { completionBlock(returnArray, nil); } else { completionBlock(nil, nil); } } failure:^(AFHTTPRequestOperation *operation, NSError *error) { EDLog(@"%@", error); completionBlock(nil, [MDError errorAFNetworking:error]); }]; } ```