我使用dispatch_group_t
来处理我的三个网络请求,代码如下:
dispatch_group_t group = dispatch_group_create();
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
[self.permissionData removeAllObjects];
dispatch_group_async(group, queue, ^{
[self getOneData];
});
[self.bannerData removeAllObjects];
dispatch_group_async(group, queue, ^{
[self getTwoData];
});
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
[self.tableView.mj_header endRefreshing];
});
和
- (void)getOneData {
[self requestData:^(id _Nullable datas, NSError * _Nullable error) {
if (error != nil) {
[self.tableView.mj_header endRefreshing];
} else {
if ([datas isKindOfClass:[NSArray class]]) {
self.datas = datas;
}
[self.tableView reloadData];
}
}];
}
这将导致两个方法getOneData
和getTwoData
的回调都执行两次。我不知道为什么他们都去两次,但如果我不使用dispatch_group_t
,没有问题。我能问问为什么吗?
2条答案
按热度按时间dwbf0jvd1#
由于您在提交的块中所做的工作本身是异步的,因此您不能依赖
dispatch_group_async
来管理组的进入和退出。您需要在调用每个函数之前调用
dispatch_group_enter
,并在每个函数的完成处理程序中调用dispatch_group_leave
。使用您当前的代码,在提交区块时进入组,在完成提交区块时离开组。
因为
requestData
是异步的,所以getOneData
返回,但是网络操作没有完成。由于
getOneData
(可能还有getTwoData
)是异步的,所以从异步块调用它没有什么价值。还有一个bug,
getOneData
的完成处理程序和dispatch_group_notify
都调用了endRefreshing
。如果在第一个数据请求中有错误,这将导致“不平衡调用”异常。8ljdwjyq2#
dispatch_group_async
将立即进入组,并在被调用的块返回时离开组。但这些块只是调用启动异步任务的方法,但不知道工作何时完成。实际效果是,调度组将在这两个异步任务一启动就得到提前通知,而不是在异步工作完成时得到通知。因此,挑战在于如何延迟分派组直到异步工作完成。我们经常会用到completion handler块:
我们也会对第二个API调用做同样的事情。
这样,我们现在可以在进行异步调用之前“进入”组,并且只在完成处理程序块中“离开”组,例如:
作为一般规则,如果您有一个异步方法,那么谨慎的做法是为它提供完成处理程序块参数,在异步方法完成时调用该参数。如果您认为可能不需要该参数,请将其设置为
_Nullable
(这就是为什么在调用它之前要检查它是否为null)。