32

我正在使用新的 NSURLSession API 并允许用户下载文件。我想尝试告诉我的 NSURLSession 要同时运行多少次下载,但我看不到这样做的方法。我想尽量避免自己管理下载任务,如果我可以告诉系统允许多少个下载任务会更好 - 当我的应用程序未运行时,这对于排队后台下载也更好。有没有办法做到这一点?

4

2 回答 2

22

您可以在具有属性的NSURLSessionConfiguration对象中设置它。HTTPMaximumConnectionsPerHost

于 2014-01-02T18:05:13.060 回答
15

我找到了解决此超时的方法。

尝试在设备上下载具有慢速连接模拟的文件(设置 -> 开发人员 -> 网络链接调节器 -> 选择配置文件 -> 3G -> 启用)。

这是我的示例代码:

- (void) methodForNSURLSession{
  NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration];
  _tasksArray = [[NSMutableArray alloc] init];
  sessionConfig.HTTPMaximumConnectionsPerHost = 3;
  sessionConfig.timeoutIntervalForResource = 120;
  sessionConfig.timeoutIntervalForRequest = 120;
  NSURLSession* session = [NSURLSession sessionWithConfiguration:sessionConfig delegate:self delegateQueue:nil];

  // data tasks
  [self createDownloadTasksWithSession:session];

}

- (void) createDownloadTasksWithSession:(NSURLSession *)session{
  for (int i = 0; i < 100; i++) {
    NSURLSessionDownloadTask *sessionDownloadTask = [session downloadTaskWithURL: [NSURL URLWithString:@"https://discussions.apple.com/servlet/JiveServlet/showImage/2-20930244-204399/iPhone%2B5%2BProblem2.jpg"]];
    [_tasksArray addObject:sessionDownloadTask];
    [sessionDownloadTask addObserver:self forKeyPath:@"countOfBytesReceived" options:NSKeyValueObservingOptionOld context:nil];
    [sessionDownloadTask resume];
  }
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{
  if([[change objectForKey:@"old"] integerValue] == 0){
    NSLog(@"task %d: started", [_tasksArray indexOfObject: object]);
  }
}

- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error{
    if (!error) {
      NSLog(@"task %d: finished!", [_tasksArray indexOfObject:task]);
    } else if (error.code == NSURLErrorTimedOut) {
      NSLog(@"task %d: timed out!", [_tasksArray indexOfObject:task]);
    }
}

我的输出:

2014-01-10 10:38:48.769 TestApplication[2442:1803] task 1: started
2014-01-10 10:38:49.517 TestApplication[2442:1803] task 2: started
2014-01-10 10:38:50.273 TestApplication[2442:4b03] task 0: started
2014-01-10 10:40:11.794 TestApplication[2442:5003] task 2: finished!
2014-01-10 10:40:13.924 TestApplication[2442:1803] task 3: started
2014-01-10 10:40:26.221 TestApplication[2442:1d0f] task 1: finished!
2014-01-10 10:40:28.487 TestApplication[2442:1d0f] task 4: started
2014-01-10 10:40:43.007 TestApplication[2442:440f] task 5: timed out!
2014-01-10 10:40:43.009 TestApplication[2442:440f] task 6: timed out!
2014-01-10 10:40:43.011 TestApplication[2442:440f] task 7: timed out!
...

如您所见,任务在 2 分钟后开始超时

我使用了timeoutIntervalForResourcetimeoutIntervalForRequest 参数,如果我们将两者都设置为 0,它将在没有超时的情况下下载。但我认为这不是一个好主意,因为电池耗电。我认为 10 分钟或类似的时间将是一个很好的价值。但是您必须将两个参数设置为相同的值。

苹果文档:

timeoutIntervalForRequest- 等待附加数据时使用的超时间隔。timeoutIntervalForResource- 一个资源请求应该被允许占用的最长时间。(所有任务对一个资源的超时)

注意到奇怪的事情:如果我们设置timeoutIntervalForResource = 60and timeoutIntervalForRequest = 30,任务将在 30 秒后超时!但他们中的大多数甚至都不会开始!

看起来像timeoutIntervalForRequest任务恢复时启动的计时器。在这种情况下,我们同时恢复了所有任务,每个任务的超时都必须作为资源超时。

另外,我可以建议wwdc13 705 会话,并提供有关下载任务的后台会话的精彩演示。

于 2014-01-09T09:20:01.743 回答