iOS 后台下载
官方指引
创建后台下载任务
创建一个会话配置对象,允许在后台执行 HTTP 和 HTTPS 上传或下载:
class func background(withIdentifier identifier: String) -> URLSessionConfiguration
使用此方法初始化适合在应用程序在后台运行时传输数据文件的配置对象。使用此对象配置的会话将传输控制权移交给系统,系统在单独的进程中处理传输。在 iOS 中,即使应用程序本身暂停或终止,此配置也可以继续传输。
如果 iOS 应用程序被系统终止并重新启动,该应用程序可以使用相同的标识符来创建新的配置对象和会话,并检索终止时正在进行的传输的状态。此行为仅适用于系统正常终止应用程序。如果用户从多任务屏幕终止应用程序,系统将取消会话的所有后台传输。此外,系统不会自动重新启动用户强制退出的应用程序。用户必须明确地重新启动应用程序才能重新开始传输。
您可以使用 isDiscretionary 属性配置后台会话以根据系统的判断安排传输以获得最佳性能。传输大量数据时,建议您将此属性的值设置为 true。有关使用后台配置的示例,请参阅在后台下载文件。
Access the File, or Move It to a Permanent Location
一旦您恢复的应用程序调用完成处理程序,下载任务完成其工作并调用委托的 urlSession(_:downloadTask:didFinishDownloadingTo:) 方法。此时,文件已完全下载,并且在您的委托方法返回之前可用。如果您只需要阅读一次,您可以立即在其临时位置访问该文件。如果要保留文件,请将其移动到像 Documents 目录这样的永久位置,如从网站下载文件中所述。
Recreate the Session If the App Was Terminated
如果系统在暂停时终止应用程序,系统会在后台重新启动应用程序。作为启动时间设置的一部分,使用与以前相同的会话标识符重新创建后台会话,以允许系统将后台下载任务与您的会话重新关联。您这样做是为了让您的后台会话准备就绪,无论应用程序是由用户启动还是由系统启动。应用程序重新启动后,一系列事件与应用程序已暂停和恢复相同,如前面处理应用程序暂停中所述。
注意:如果在应用程序处于后台时启动传输,则会话配置的 isDiscretionary 属性被视为 true。
Comply with Background Transfer Limitations
对于后台会话,实际传输由与您的应用程序进程分开的进程执行。由于重新启动应用程序的进程相当昂贵,因此一些功能不可用,从而导致以下限制:
- 会话必须为事件传递提供委托。对于上传和下载,委托的行为与进程内传输相同
- 仅支持 HTTP 和 HTTPS 协议,不支持自定义协议
- 始终遵循重定向。结果,即使你已经实现了
urlSession(_:task:willPerformHTTPRedirection:newRequest:completionHandler:),它也不会被调用 - 仅支持从文件上传任务,应用退出后从数据实例或流上传失败
Use Background Sessions Efficiently
当系统恢复或重新启动您的应用程序时,它会使用速率限制器来防止滥用后台下载。当您的应用在后台启动新的下载任务时,该任务在延迟到期之前不会开始。每次系统恢复或重新启动您的应用程序时,延迟都会增加。
因此,如果您的应用程序开始单个后台下载,下载完成后恢复,然后开始新的下载,这将大大增加延迟。相反,使用少量后台会话(理想情况下只有一个)并使用这些会话一次启动许多下载任务。这允许系统一次执行多个下载,并在完成后恢复您的应用程序。
但请记住,每个任务都有自己的开销。如果您发现需要启动数千个下载任务,请更改您的设计以执行更少、更大的传输。
注意:每当用户将您的应用程序置于前台时,延迟都会重置为 0。如果延迟时间过去而系统没有恢复或重新启动您的应用程序,它也会重置。
DownloadTask 断点续传
A download can be resumed only if the following conditions are met:
- The resource has not changed since you first requested it
- The task is an HTTP or HTTPS GET request
- The server provides either the ETag or Last-Modified header (or both) in its response
- The server supports byte-range requests
- The temporary file hasn’t been deleted by the system in response to disk space pressure
Download Delegate Behavior
When you use a download task, your delegate receives several callbacks unique to download scenarios.
During download, the session periodically calls the delegate’s
urlSession(_:downloadTask:didWriteData:totalBytesWritten:totalBytesExpectedToWrite:)method with status information.Upon successful completion, the session calls the delegate’s
urlSession(_:downloadTask:didFinishDownloadingTo:)method or completion handler. In that method, you must either open the file for reading or move it to a permanent location in your app’s sandbox container directory.Upon unsuccessful completion, the session calls the delegate’s
urlSession(_:task:didCompleteWithError:)method or completion handler. The only errors your delegate receives through the error parameter are client-side errors, such as being unable to resolve the hostname or connect to the host. To check for server-side errors, inspect the response property of the task parameter received by this callback.