- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我正在调用一个方法,该方法将枚举一个数组,创建一个 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];
}
最佳答案
有多种选择。根本问题是这些单独的数据任务是异步运行的,因此您需要某种方式来跟踪这些异步任务并对它们的完成建立某种依赖性。
有几种可能的方法:
典型的解决方案是使用调度组。在使用 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
});
}
处理这个问题的更复杂的方法是将 NSSessionDataTask
包装在 NSOperation
子类中,然后您可以在数据任务操作和最终操作之间使用依赖关系完成操作。您需要确保您的个人数据任务操作是“并发”操作(即在异步数据任务完成之前不要发出 isFinished
通知)。这种方法的好处是您可以设置 maxConcurrentOperationCount
来限制在任何给定时间将启动多少请求。通常,您希望一次将其限制为 3-4 个请求。
请注意,这也可以解决调度组方法可能遇到的超时问题。调度组不限制在任何给定时间提交的请求数量,而这可以通过 NSOperation
轻松实现。
有关详细信息,请参阅 Operation Queue 中有关“并发操作”的讨论。 并发编程指南的部分。
有关在异步NSOperation
子类中包装NSURLSessionTask
请求的示例,请参阅后半部分的简单实现NSURLSession with NSBlockOperation and queues .这个问题是针对不同的主题,但我在最后包含了一个 NSOperation
子类示例。
如果您使用上传/下载任务而不是数据任务,那么您可以使用 [NSURLSessionConfiguration backgroundSessionConfiguration]
和 URLSessionDidFinishEventsForBackgroundURLSession:
您的 NSURLSessionDelegate
然后会在所有任务完成并且应用程序返回前台时被调用。 (虽然有点烦人,但只有在下载完成时您的应用程序未激活时才会调用此方法:我希望即使下载完成时应用程序在前台也能调用此委托(delegate)方法的再现。)
虽然您询问了数据任务(不能与后台 session 一起使用),但将后台 session 与上传/下载任务一起使用具有后台操作的显着优势。如果您的过程真的需要 10 分钟(这看起来很不寻常),为后台 session 重构它可能会带来显着的优势。
我什至不想提这个,但为了完整起见,我应该承认理论上你可以通过维护一个可变数组或待处理数据任务的字典,并在每个数据任务完成后,删除该列表中的一个项目,如果它得出的结论是最后一个任务,则手动启动完成过程。
关于objective-c - 如何知道 NSURLSessionDataTask 的 for 循环何时完成,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20735646/
我有一个使用 NSURLSessionDataTask 调用 API 的函数,您可以在此处查看它: - (void)getExplorerUrl:(void (^)(NSString *))measu
我正在尝试向服务器发出请求,该请求应该返回我可以在应用程序的其余部分中使用的数据。这是我的代码: func makeNewUser() -> NSDictionary { var full_u
我正在使用 AFNetworking 并且我正在覆盖 -dataTaskWithRequest:completionHandler: 以基本上 MITM 我的请求并在调用实际响应 block 之前进行
我使用 NSURLSessionDataTask 获取 JSON 提要,并填充位于共享存储(单例)内的 NSMutableArray。外部世界可以通过将其转换为 NSArray 的 getter 来访
我不知道如何同步 NSURLSessionDataTask。 如何在 syncInfo1Info2 中同步这两个 session : - (void) syncInfo1Info2 { //How
我想知道 NSURLSessionDataTask 在后台的行为。 NSURLSessionDataTask 是否会立即暂停(一旦应用程序进入后台)?还是 iOS 会给出一些时间(希望有 30 秒左右
我正在创建一个 NSMutableRequest: self.req = [NSMutableURLRequest requestWithURL:myURL cachePolicy:NSURLRequ
当我开始使用 NSURLSessionDataTask 下载文件时,有一段时间进度不工作。然后在完成下载后只显示全蓝色的进度条。 我的代码 - (void)URLSession:(NSURLSess
我对 Objective C 和 iOS 开发总体来说是新手。我正在尝试创建一个应用程序,它会发出 http 请求并在标签上显示内容。 当我开始测试时,我注意到标签是空白的,尽管我的日志显示我已经恢复
我正在学习有关访问 API 和解析结果的教程。我正在逐字逐句地学习教程,但由于“预期返回‘NSURLSessionDataTask’的函数中缺少返回值”,我无法运行该程序 所以我将返回语句更改为“re
我要使用 NSURLSessionDataTask 执行请求链。当第一个请求完成时,我需要使用第一个请求中的 responseData 来执行另一个多重请求。最后,我得到 NSArray 并提供给 T
我正在尝试从将同时运行的多个 NSURLSessionDataTasks 中聚合数据。 __block NSMutableDictionary *languageDetails = [NSMutabl
我刚刚用 Swift 开发了一个库,用于将数据发布到特定服务器。我使用 NSURLSession.sharedSession().dataTaskWithRequest(request) 打开连接。现
我有一个 iOS 应用程序,它使用 NSOperationQueue、NSOperations 和 AFNetworking 2.1.0 来触发对服务器的请求。 -[NSOperation main]
我知道我可以使用 dataTaskWithURL:completionHandler: 获取 completionHandler block 中的数据,但这会阻止触发委托(delegate)方法,我需
场景: 作为用户,我可以拍摄(无限量)存储在应用程序文档文件夹中的照片和视频。这些媒体文件中的每一个都会在 Sqlite 数据库中获得一条记录,其中包含附加信息(例如标题)。所有这些都可以完全离线完成
在使用 NSURLSessionDataTask 向服务器发送 JSON 请求时,我遇到了一个非常奇怪的问题。 第一个请求通过并且我收到正确的 JSON 响应,当我执行第二个请求时,我总是得到旧的响应
我想确定来自 NSURLSessionDataTask 的响应是来自缓存,还是来自服务器 我正在从 创建我的 NSURLSessionDataTask request.cachePolicy = NS
我有一个注册 View Controller ,它处理所有用户输入并调用传递给它的另一个类 (wsClass) 中的函数,该数据作为 NSDictionary。 调用 wsClass 中的函数并建立连
我从 Web 获取 JSON 数据,对其进行解析,然后使用它在 map 上显示图钉。 这里是方法一,没有问题: NSString *CLIENT_ID = @"SECRET_ID"; NSSt
我是一名优秀的程序员,十分优秀!