我有一个包含三个异步方法的for循环,我想在这3个异步方法完成后进行一些处理。
-(void)getAllUsersInformations{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
for(User *user in users){
[self getUserInfo:user];
}
//Here, I want to reload the table view for example, after finishing the for loop (executing the whole three methods).
});
}
-(void)getUserInfo:(User*)user{
[self getInformations:user];
[self getExperiences:user];
[self getEducation:user];
}
你有什么技术可以得到这个结果吗?
非常感谢。
一种 GCD 方法是使用dispatch_group
。因此,在启动异步任务之前,请调用dispatch_group_enter
,然后当异步任务完成时,调用dispatch_group_leave
,然后您可以创建一个dispatch_group_notify
当异步任务完成时将调用它。您可以将其与完成块模式结合起来(无论如何,这对于异步方法来说是一个好主意):
-
If getInformations
, getExperiences
and getEducation
它们本身都是异步方法,您需要的第一件事是某种机制来知道它们何时完成。一个常见的解决方案是为每个实现一个完成块模式。例如:
// added completionHandler parameter which will be called when the retrieval
// of the "informations" is done.
- (void)getInformations:(User*)user completionHandler:(void (^)(void))completionHandler {
// do whatever you were before, but in the asynchronous task's completion block, call this
// completionHandler()
//
// for example
NSURLRequest *request;
[NSURLConnection sendAsynchronousRequest:request queue:nil completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
// handle the request here
// the important thing is that the completion handler should
// be called _inside_ the this block
if (completionHandler) {
completionHandler();
}
}];
}
重复此过程getExperiences
and getEducation
, too.
-
然后,您可以使用调度组来通知您这三个请求中的每一个何时完成,并调用完成块getUserInfo
当这种情况发生时:
// added completion handler that will be called only when `getInformations`,
// `getExperiences` and `getEducation` are all done.
//
// this takes advantage of the completion block we added to those three
// methods above
- (void)getUserInfo:(User*)user completionHandler:(void (^)(void))completionHandler {
dispatch_group_t group = dispatch_group_create();
// start the three requests
dispatch_group_enter(group);
[self getInformations:user completionHandler:^{
dispatch_group_leave(group);
}];
dispatch_group_enter(group);
[self getExperiences:user completionHandler:^{
dispatch_group_leave(group);
}];
dispatch_group_enter(group);
[self getEducation:user completionHandler:^{
dispatch_group_leave(group);
}];
// this block will be called asynchronously only when the above three are done
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
if (completionHandler) {
completionHandler();
}
});
}
-
然后你重复这个过程getAllUsersInformations
:
// call new getUserInfo, using dispatch group to keep track of whether
// all the requests are done
-(void)getAllUsersInformations {
dispatch_group_t group = dispatch_group_create();
for(User *user in users){
dispatch_group_enter(group);
[self getUserInfo:user completionHandler:^{
dispatch_group_leave(group);
}];
}
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
[self.tableView reloadData];
});
}
最后两个想法:
概述了所有这些之后,我必须承认我可能会将这些请求包装在并发/异步自定义中NSOperation
子类而不是使用调度组。请参阅《配置并发执行操作》部分并发编程指南 https://developer.apple.com/library/mac/documentation/General/Conceptual/ConcurrencyProgrammingGuide/OperationObjects/OperationObjects.html#//apple_ref/doc/uid/TP40008091-CH101-SW8。这是对代码的更彻底的重构,因此我不会在这里解决这个问题,但它可以让您限制同时运行的这些请求的数量,从而减轻潜在的超时问题。
我不知道有多少用户请求正在进行,但您可能需要考虑在用户信息传入时更新 UI,而不是等待一切完成。这又是对代码的更彻底的重构,但可能会导致一些感觉更灵敏的东西。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)