ios – 等待异步方法在for循环中完成

我有一个包含三个异步方法的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,当异步任务完成时将调用它.您可以将此与完成块模式结合(无论如何,这对于异步方法都是一个好主意):

>如果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();
        }
    }];
}

对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();
        }
    });
}

>然后你在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,^{
        [self.tableView reloadData];
    });
}

两个最后的想法:

>概述了所有这些,我必须承认我可能会将这些请求包装在并发/异步自定义NSOperation子类中,而不是使用调度组.请参阅Concurrency Programming Guide的“配置并发执行操作”部分.这是对代码进行更彻底的重构,因此我不会在此处解决此问题,但它允许您限制将同时运行的这些请求的数量,从而降低潜力超时问题.>我不知道有多少用户请求正在进行,但您可能需要考虑在用户信息进入时更新UI,而不是等待所有内容完成.这又是对代码进行更彻底的重构,但可能会导致更具响应性的内容.

相关文章

当我们远离最新的 iOS 16 更新版本时,我们听到了困扰 Apple...
欧版/美版 特别说一下,美版选错了 可能会永久丧失4G,不过只...
一般在接外包的时候, 通常第三方需要安装你的app进行测...
前言为了让更多的人永远记住12月13日,各大厂都在这一天将应...