iOS URLSession 在后台启动下载任务

iOS URLSession Initiate DownloadTask in Background

我正在尝试构建一个顺序下载管理器,用户可以在其中一次启动多达 1000 个下载任务,但实际上只有 2 个会下载,其余的将被搁置,直到两个中的一个完成,以便另一个一个998就可以启动了。

因为没有办法添加一个downloadTask然后让那个任务等别人完成然后自动开始,我自己建立了一个下载队列,只会在创建新的downloadTask时旧的完成。

我已经阅读了文档并且非常了解iOS处理后台下载事件的机制,以及我需要实现哪些方法才能正确处理它们。但是,我找不到任何关于在旧的 IN BACKGROUND 完成时启动新的 downloadTask 是否安全可靠的信息。

主要问题:

当 iOS 在后台重新启动我的应用程序以通知我下载任务已完成时,我可以可靠地 创建一个新的 downloadTask 并将其添加到当前会话?如果是这样,当该任务也完成时,系统会再次重新启动我的应用程序以告诉我它已完成吗?如果是这样,那么我可以创建一个无限循环,在旧 backgroundTask 完成时添加新任务。

代码示例

如果我一次只下载一个项目,同时应用程序完全在后台运行,下面的代码是否可以可靠地下载整个下载队列(比如 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()
      }
    }
  } 
}

您正在创建 URLSessionDownloadTask,但从未以 resume() 开始。


FWIW,即使您修复了上述问题,您也应该认识到,当应用 运行在后台模式下提交的请求将始终以自主模式提交。作为 the docs 对于 isDiscretionary 说:

For transfers started while your app is in the background, the system always starts transfers at its discretion—in other words, the system assumes this property is true and ignores any value you specified.

另外,要认识到每次请求完成时让系统启动您的应用程序以提交下一个请求既效率低下(因为您的应用程序会不断启动并返回后台)又慢(因为并发请求减少延迟影响)。通常最好在应用程序处于活动状态时预先提交所有请求,并让后台会话管理它允许同时 运行 的请求数。