两个并发的后台任务需要修补需要在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]);
}];
}
答案 0 :(得分:14)
这是因为您的getPath
方法异步运行。在完成块运行之前,您需要它不离开组。因此,您应该手动dispatch_group_async
和dispatch_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
});