dispatch_group_notify不等待一个dispatch_group_async

时间:2014-05-23 12:05:53

标签: ios asynchronous queue objective-c-blocks grand-central-dispatch

两个并发的后台任务需要修补需要在dispatch_group_notify块中合并的两个单独的数组。问题在于,超出了第一个块但超出了dispatch_group_notify而没有等待执行第二个后台任务。 它们之间唯一不同的是第一个进行本地搜索,第二个远程调用Web服务。任何线索为什么第二个被跳过?

编辑:我也尝试使用dispatch_barrier_async在https://stackoverflow.com/a/19580584/859742中提到的方法但仍然相同。

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

远程搜索方法如下所示

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

1 个答案:

答案 0 :(得分:14)

这是因为您的getPath方法异步运行。在完成块运行之前,您需要它不离开组。因此,您应该手动dispatch_group_asyncdispatch_group_enter,而不是执行dispatch_group_leave

您可以更改以下代码:

dispatch_group_async(taskGroup, mainQueue, ^{
    [[MDAddressManager instance] searchForPlacesContainingText:query
                                                      location:alocation
                                                    completion:^(NSArray* addresses, MDError *error){
        //remoteAddresses is set
    }];
});

要:

dispatch_group_enter(taskGroup);

[[MDAddressManager instance] searchForPlacesContainingText:query
                                                  location:alocation
                                                completion:^(NSArray* addresses, MDError *error){
    //remoteAddresses is set
    dispatch_group_leave(taskGroup);
});

这将确保在调用完成块之前不要离开组。


或者,您可以将searchForPlacesContainingText更改为使用dispatch_group_t参数:

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

}

并更改您的调用,使其不会dispatch_group_async,而只是传递taskGroup参数:

[[MDAddressManager instance] searchForPlacesContainingText:query
                                                  location:alocation
                                                     group:taskGroup
                                                completion:^(NSArray* addresses, MDError *error) {
    //remoteAddresses is set
});