Подтвердить что ты не робот

Установить количество одновременных загрузок с помощью NSURLSessionDownloadTask

Я использую новый API NSURLSession и позволяю пользователю загружать файлы. Я хотел бы попытаться рассказать моему NSURLSession, сколько одновременных загрузок нужно запускать, но я не вижу способа сделать это. Я хотел бы попытаться избежать управления задачами загрузки самостоятельно, было бы намного лучше, если бы я мог сказать системе, сколько из них разрешить - это было бы лучше для загрузки очередей в фоновом режиме, когда мое приложение не будет работать. Есть ли способ сделать это?

4b9b3361

Ответ 1

Вы можете установить его в объекте NSURLSessionConfiguration с помощью свойства HTTPMaximumConnectionsPerHost.

Ответ 2

Я нашел обходной путь для этих тайм-аутов.

Пробовал загружать файл с медленным симуляцией соединения на устройстве (Настройки → Разработчик → Сетевой клик → Выберите профиль → 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 минуты

Я играл с параметрами timeoutIntervalForResource и timeoutIntervalForRequest, и в случае, если мы установили оба значения в 0, он будет загружаться без тайм-аутов. Но я думаю, что это не очень хорошая идея, потому что аккумулятор нарисован. Я думаю, что 10 минут или что-то в этом роде будут для него полезными. Но вы должны установить оба параметра на одно и то же значение.

Apple docs:

timeoutIntervalForRequest - Интервал таймаута для использования при ожидании для получения дополнительных данных. timeoutIntervalForResource - максимальная сумма времени, когда запрос ресурса должен быть разрешен. (тайм-аут для все задания на один ресурс)

Заметили странную вещь: если мы установим timeoutIntervalForResource = 60 и timeoutIntervalForRequest = 30, задачи будут отключены через 30 секунд! Но большинство из них даже не запустится!

Похоже, что таймер для timeoutIntervalForRequest запускается, когда задача возобновляется. В этом случае мы возобновили все задачи в одно и то же время, и каждый тайм-аут задачи должен быть как тайм-аут ресурса.

Кроме того, я могу посоветовать wwdc13 705 session с отличной демонстрацией о фоновой сессии с задачей загрузки.