我有一个包含三个异步方法的for循环,我想在这三个异步方法完成之后进行一些处理。
-(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];
}
你有什么技术可以得到这个结果吗?非常感谢。
发布于 2014-10-13 07:48:51
GCD的一种方法是使用dispatch_group
。因此,在启动异步任务之前,调用dispatch_group_enter
,然后在异步任务完成时调用dispatch_group_leave
,然后创建一个dispatch_group_notify
,该dispatch_group_notify
将在异步任务完成时被调用。您可以将它与完成块模式结合起来(这对于异步方法来说是个好主意):
getInformations
、getExperiences
和getEducation
本身都是异步方法,那么首先需要某种机制来了解它们何时完成。一个常见的解决方案是为每个模块实现一个完成块模式。例如:
//添加了completionHandler参数,该参数将在检索//完成“信息”时调用。-(Void)getInformations:(user*) completionHandler:(void (^)(void))completionHandler {/做您以前做的任何事情,但是在异步任务的完成块中,调用这个// completionHandler() /,例如NSURLRequest *请求;NSURLConnection sendAsynchronousRequest:请求队列:nil完成处理程序:^(NSURLResponse *response,NSData *data,NSError *connectionError) { //处理这里的请求//重要的是,如果(completionHandler) { completionHandler();}},完成处理程序应该//被称为_inside_这个块;};
对getExperiences
和getEducation
也重复此过程。getUserInfo
中的一个完成块:
//添加的完成处理程序,只有在getInformations
、/ getExperiences
和getEducation
都完成时才会调用。/这利用了我们添加到上述三种//方法中的完成块- (void)getUserInfo:(User*)user completionHandler:(void (^)(void))completionHandler { dispatch_group_t group = dispatch_group_create();//启动三个请求dispatch_group_enter(组);自获取体验:用户完成处理程序:^{ dispatch_group_leave(组);};dispatch_group_enter(组);自getEducation:用户完成处理程序:^{dispatch_group_leave(组);};//此块只有在完成dispatch_group_notify(组、dispatch_get_main_queue()、^{ if (completionHandler) {completionHandler())时才能异步调用;});}getAllUsersInformations
中重复这个过程:
//调用新getUserInfo,使用调度组跟踪是否完成了//所有请求-(getAllUsersInformations{ dispatch_group_t组= dispatch_group_create();for(用户*用户){dispatch_group_enter(组);self getUserInfo:用户完成处理程序:^{dispatch_group_leave(组);};}dispatch_group_notify(组,dispatch_get_main_queue(),^{ self.tableView reloadData;});}最后两个想法:
NSOperation
子类中,而不是使用分派组。请参阅Concurrency Programming Guide的“为并发执行配置操作”一节。这是对代码的更激进的重构,所以我不会在这里讨论这个问题,但是它允许您限制将同时运行的这些请求的数量,从而减少潜在的超时问题。发布于 2014-10-13 07:42:03
尝试完成一个块,如果方法是异步的,就不能用for循环来完成。在完成前面的操作之后,您必须一个一个地调用getUserInfo。我想这会解决你的问题。
-(void)getAllUsersInformations{
[self registerUserAtIndex:0];
}
- (void) registerUserAtIndex: (NSInteger ) userIndex
{
RegisterOperation *op = [[RegisterOperation alloc] initWithUser:[users objectAtIndex:userIndex]];
[RegisterOperation setResultCompletionBlock:^(BOOL *finished, NSInteger userIndex) {
dispatch_async(dispatch_get_main_queue(), ^{
if (userIndex++ < [users count] {
[self registerUserAtIndex:userIndex++];
} else {
[myTableView reloadData];
}
}];
[[NSOperationQueue mainQueue] addOperation:op];
}
希望这能帮到你。
发布于 2017-01-05 03:25:23
用快速回答Rop
func processData()
{
let group: dispatch_group_t = dispatch_group_create()
for item in data as! Object {
dispatch_group_enter(group)
item.process(completion: {() -> (Void) in
dispatch_group_leave(group)
})
}
dispatch_group_notify(group, dispatch_get_main_queue(), {
//Do whatever you want
})
}
https://stackoverflow.com/questions/26343351
复制