and*_*nnn 6 grand-central-dispatch ios
我有一个包含三个异步方法的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];
}
Run Code Online (Sandbox Code Playgroud)
你有任何技术可以得到这个结果吗?非常感谢你.
Rob*_*Rob 15
一种GCD方法是使用dispatch_group.因此,在启动异步任务之前,调用dispatch_group_enter,然后在异步任务完成时调用dispatch_group_leave,然后可以创建dispatch_group_notify在异步任务完成时调用的任务.您可以将此与完成块模式结合(无论如何,这对于异步方法都是一个好主意):
如果getInformations,getExperiences以及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();
}
}];
}
Run Code Online (Sandbox Code Playgroud)
重复此过程getExperiences,并getEducation也.
然后,您可以使用调度组通知您这三个请求中的每个请求何时完成,并在发生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();
}
});
}
Run Code Online (Sandbox Code Playgroud)然后你重复这个过程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];
});
}
Run Code Online (Sandbox Code Playgroud)两个最后的想法:
概述了所有这些,我必须承认我可能会将这些请求包装在并发/异步自定义NSOperation子类中,而不是使用调度组.请参阅" 并发编程指南 "的"配置并发执行操作"部分.这是对代码进行更彻底的重构,所以我不会在这里解决这个问题,但是它可以让你限制同时运行的这些请求的数量,从而减少潜在的超时问题.
我不知道有多少这些用户请求正在进行,但您可能需要考虑在用户信息进入时更新UI,而不是等待所有内容完成.这又是对代码进行更彻底的重构,但可能会导致更具响应性的内容.
| 归档时间: |
|
| 查看次数: |
4348 次 |
| 最近记录: |