Objective c 如何知道NSURLSessionDataTasks的for循环何时完成
我正在调用一个方法,该方法将枚举一个数组,创建一个NSURL,并调用一个返回JSON的NSURLSessionDataTask。循环通常运行10次左右,但根据日期的不同而有所不同 我需要等待for循环和所有NSURLSessionDataTasks完成,然后才能开始处理数据 我很难弄清楚所有的工作什么时候完成。有谁能推荐一些方法或逻辑来知道整个方法何时完成(对于循环和数据任务) }看看你的例子,大致如下:Objective c 如何知道NSURLSessionDataTasks的for循环何时完成,objective-c,loops,ios7,objective-c-blocks,nsurlsession,Objective C,Loops,Ios7,Objective C Blocks,Nsurlsession,我正在调用一个方法,该方法将枚举一个数组,创建一个NSURL,并调用一个返回JSON的NSURLSessionDataTask。循环通常运行10次左右,但根据日期的不同而有所不同 我需要等待for循环和所有NSURLSessionDataTasks完成,然后才能开始处理数据 我很难弄清楚所有的工作什么时候完成。有谁能推荐一些方法或逻辑来知道整个方法何时完成(对于循环和数据任务) }看看你的例子,大致如下: create group for (url in urls) enter g
create group
for (url in urls)
enter group
start_async_task
when complete leave group
wait on group to finish or supply a block to be run when completed
有很多选择。基本问题是这些单独的数据任务是异步运行的,因此您需要某种方法来跟踪这些异步任务,并对它们的完成建立某种依赖关系 有几种可能的方法:
dispatch\u group\u Enter
启动请求之前,请输入组,将使用dispatch\u group\u leave
的组保留在完成处理程序中(异步调用),然后在循环结束时,提供一个dispatch\u group\u notify
块,当所有“Enter”命令执行完毕时,该块将异步调用呼叫被相应的“离开”呼叫抵消:
NSSessionDataTask
包装在NSOperation
子类中,然后可以使用数据任务操作和最终完成操作之间的依赖关系。您需要确保您的单个数据任务操作是“并发”操作(即,在异步数据任务完成之前,不要发出isFinished
通知)。这种方法的好处是,您可以设置maxConcurrentOperationCount
,以限制在任何给定时间启动的请求数量。通常,您希望一次将其限制为3-4个请求
注意,这还可以解决调度组方法可能遇到的超时问题。调度组不限制在任何给定时间提交的请求数量,而这可以通过NSOperation
轻松实现
有关更多信息,请参阅《并发编程指南》一节中关于“并发操作”的讨论
有关在异步NSOperation
子类中包装NSURLSessionTask
请求的示例,请参见下半部分的简单实现。这个问题是针对一个不同的主题,但我在最后包含了一个NSOperation
子类示例[NSURLSessionConfiguration backgroundSessionConfiguration]
和urlsessiondFinisheventsforbackgroundurlsession:
的nsurlsessionelegate
将在所有任务完成且应用程序返回前台时被调用。(不过,有一点让人恼火的是,只有在下载完成时应用程序未处于活动状态时才会调用此方法:我希望有一个此委托方法的格式副本,即使下载完成时应用程序位于前台也会调用此方法。)
当您询问数据任务(不能与后台会话一起使用)时,将后台会话与上载/下载任务一起使用具有后台操作的显著优势。如果您的过程真的需要10分钟(这看起来很特别),那么为后台会话重构这个过程可能会提供显著的优势您的任务已在completionHandler block.BTW中完成,如果使用此技术,请确保任务同步(例如使用信号量),否则您的组将在所有任务排队后“完成”,而不是在所有任务完成时。
create group
for (url in urls)
enter group
start_async_task
when complete leave group
wait on group to finish or supply a block to be run when completed
- (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
});
}