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

Original source

Related problems