gpt4 book ai didi

objective-c - 如何知道 NSURLSessionDataTask 的 for 循环何时完成

转载 作者:太空狗 更新时间:2023-10-30 04:00:07 25 4
gpt4 key购买 nike

我正在调用一个方法,该方法将枚举一个数组,创建一个 NSURL,然后调用一个返回 JSON 的 NSURLSessionDataTask。该循环通常运行大约 10 次,但可能会因日期而异。

在开始处理数据之前,我需要等待 for 循环和所有 NSURLSessionDataTasks 完成。

我很难确定所有工作何时完成。谁能推荐任何方法或逻辑来了解整个方法何时完成(对于循环和数据任务)?

-(void)findStationsByRoute{
for (NSString *stopID in self.allRoutes) {
NSString *urlString =[NSString stringWithFormat:@"http://truetime.csta.com/developer/api/v1/stopsbyroute?route=%@", stopID];
NSURL *url = [NSURL URLWithString:urlString];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
NSURLSessionDataTask *task = [self.session dataTaskWithRequest:request
completionHandler:^(NSData *data,
NSURLResponse *response,
NSError *error) {
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
if(httpResponse.statusCode == 200){
NSError *jsonError = [[NSError alloc]init];
NSDictionary *stopLocationDictionary = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:&jsonError];
NSArray *stopDirectionArray = [stopLocationDictionary objectForKey:@"direction"];
for (NSDictionary * _stopDictionary in stopDirectionArray) {
NSArray *stop = [_stopDictionary objectForKey:@"stop"];
[self.arrayOfStops addObject:stop];

}
}

}];

[task resume];
}

最佳答案

有多种选择。根本问题是这些单独的数据任务是异步运行的,因此您需要某种方式来跟踪这些异步任务并对它们的完成建立某种依赖性。

有几种可能的方法:

  1. 典型的解决方案是使用调度组。在使用 dispatch_group_enter 开始请求之前进入组,在异步调用的完成处理程序中使用 dispatch_group_leave 离开组,然后在循环结束时,提供一个 dispatch_group_notify block ,当所有“enter”调用都被相应的“leave”调用抵消时,该 block 将被异步调用:

    - (void)findStationsByRoute {
    dispatch_group_t group = dispatch_group_create();

    for (NSString *stopID in self.allRoutes) {
    NSString *urlString = [NSString stringWithFormat:@"http://truetime.csta.com/developer/api/v1/stopsbyroute?route=%@", stopID];
    NSURL *url = [NSURL URLWithString:urlString];
    NSURLRequest *request = [NSURLRequest requestWithURL:url];

    dispatch_group_enter(group); // enter group before making request

    NSURLSessionDataTask *task = [self.session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
    NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
    if(httpResponse.statusCode == 200){
    NSError *jsonError; // Note, do not initialize this with [[NSError alloc]init];
    NSDictionary *stopLocationDictionary = [NSJSONSerialization JSONObjectWithData:data options:0 error:&jsonError];
    NSArray *stopDirectionArray = [stopLocationDictionary objectForKey:@"direction"];
    for (NSDictionary *stopDictionary in stopDirectionArray) {
    NSArray *stop = [stopDictionary objectForKey:@"stop"];
    [self.arrayOfStops addObject:stop];
    }
    }

    dispatch_group_leave(group); // leave group from within the completion handler
    }];

    [task resume];
    }

    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
    // do something when they're all done
    });
    }
  2. 处理这个问题的更复杂的方法是将 NSSessionDataTask 包装在 NSOperation 子类中,然后您可以在数据任务操作和最终操作之间使用依赖关系完成操作。您需要确保您的个人数据任务操作是“并发”操作(即在异步数据任务完成之前不要发出 isFinished 通知)。这种方法的好处是您可以设置 maxConcurrentOperationCount 来限制在任何给定时间将启动多少请求。通常,您希望一次将其限制为 3-4 个请求。

    请注意,这也可以解决调度组方法可能遇到的超时问题。调度组不限制在任何给定时间提交的请求数量,而这可以通过 NSOperation 轻松实现。

    有关详细信息,请参阅 Operation Queue 中有关“并发操作”的讨论。 并发编程指南的部分。

    有关在异步NSOperation 子类中包装NSURLSessionTask 请求的示例,请参阅后半部分的简单实现NSURLSession with NSBlockOperation and queues .这个问题是针对不同的主题,但我在最后包含了一个 NSOperation 子类示例。

  3. 如果您使用上传/下载任务而不是数据任务,那么您可以使用 [NSURLSessionConfiguration backgroundSessionConfiguration]URLSessionDidFinishEventsForBackgroundURLSession: 您的 NSURLSessionDelegate 然后会在所有任务完成并且应用程序返回前台时被调用。 (虽然有点烦人,但只有在下载完成时您的应用程序未激活时才会调用此方法:我希望即使下载完成时应用程序在前台也能调用此委托(delegate)方法的再现。)

    虽然您询问了数据任务(不能与后台 session 一起使用),但将后台 session 与上传/下载任务一起使用具有后台操作的显着优势。如果您的过程真的需要 10 分钟(这看起来很不寻常),为后台 session 重构它可能会带来显着的优势。

  4. 我什至不想提这个,但为了完整起见,我应该承认理论上你可以通过维护一个可变数组或待处理数据任务的字典,并在每个数据任务完成后,删除该列表中的一个项目,如果它得出的结论是最后一个任务,则手动启动完成过程。

关于objective-c - 如何知道 NSURLSessionDataTask 的 for 循环何时完成,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20735646/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com