iOS URLSession Инициировать задачу загрузки в фоновом режиме - PullRequest
0 голосов
/ 26 мая 2020

Я пытаюсь создать диспетчер последовательной загрузки, в котором пользователь может инициировать до 1000 задач загрузки одновременно, но на самом деле будут загружены только 2, а остальные будут приостановлены, пока не завершится одно из двух, так что еще одно из 998 может запуститься.

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

Я прочитал документацию и хорошо осведомлен о механизме обработки iOS события фоновой загрузки и о том, какие методы мне нужно реализовать, чтобы обрабатывать их правильно. Однако я не могу найти ничего о том, безопасно и надежно ли запускать новый downloadTask, когда старый завершается НА ФОНЕ.

Основной вопрос:

Когда iOS перезапускает мое приложение в фоновом режиме, чтобы сообщить мне, что мои задачи загрузки завершены, могу ли я надежно создать новый downloadTask и добавить его в текущий сеанс? Если да, то когда эта задача также завершится, система снова запустит мое приложение СНОВА, чтобы сообщить мне, что оно завершено? Если это так, то я могу создать бесконечный l oop добавления новых задач, когда старый backgroundTask fini sh.

Пример кода

Будет ли следующий код надежным для загрузки всей очереди загрузки (скажем, 1000 элементов), если я загружаю ТОЛЬКО один элемент за раз, а приложение тем временем остается полностью в фоновом режиме?

extension MyClass: URLSessionDelegate {
  func urlSessionDidFinishEvents(forBackgroundURLSession session: URLSession) {

    // This is called when background tasks are done
    // Let's add a new background tasks WHILE app has just been 
    // relaunched IN BACKGROUND

    if let nextURL = myURLQueue.removeFirst() {
        session.downloadTask(with: URLRequest(url: nextURL))
    }

    DispatchQueue.main.async {
      if let appDelegate = UIApplication.shared.delegate as? AppDelegate,
        let completionHandler = appDelegate.backgroundSessionCompletionHandler {
        appDelegate.backgroundSessionCompletionHandler = nil

        completionHandler()
      }
    }
  } 
}

1 Ответ

0 голосов
/ 26 мая 2020

Вы создаете URLSessionDownloadTask, но никогда не начинаете его с resume().


FWIW, даже если вы исправите вышеуказанное, вы должны понимать, что запросы, которые отправляются, когда приложение работает в фоновом режиме, всегда будут отправляться в произвольном режиме. Как документы для isDiscretionary говорят:

Для передач, запущенных, когда ваше приложение работает в фоновом режиме, система всегда начинает передачу по своему усмотрению - другими словами, система предполагает, что это свойство истинно, и игнорирует любое указанное вами значение.

Кроме того, помните, что наличие системы, запускающей ваше приложение каждый раз, когда выполняется запрос для отправки следующего запроса, неэффективно (потому что ваше приложение будет постоянно запускаться и go возвращается в фоновый режим) и медленно (потому что одновременные запросы уменьшают эффекты задержки). Как правило, лучше просто отправлять все запросы заранее, пока приложение активно, и позволить фоновому сеансу управлять количеством одновременных запусков.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...