使用 begin Background Task With Expiration Handler 进行上传

using begin​Background​Task​With​Expiration​Handler​ for upload

doc 看来上传文件是使用 begin​Background​Task​With​Expiration​Handler​ 的一个很好的用例。我发现使用

let uploadTask = session.uploadTask(with: request as URLRequest, fromFile: file)
uploadTask.resume()

已经 运行 当应用程序处于后台时(我有一段时间收到上传进度提示)。此外,我可以将 URLSession 设置为后台:

let config = URLSessionConfiguration.background(withIdentifier: "uploads")
session = URLSession(configuration: config, delegate: self, delegateQueue: nil)

那么使用 begin​Background​Task​With​Expiration​Handler 有什么好处呢?它会延长我完成上传的时间吗?如果是这样,我能知道多少(在文档中没有看到任何相关信息)?或者只是我会在应用程序停止之前收到 ping 通知?我应该将它与背景 URLSession 结合使用吗?

此外,文档说处理程序将 在应用的剩余后台时间达到 0 之前不久被调用 这是否意味着应用将在此之后终止?也就是说,我可以假设下一个电话是 application:didFinishLaunchingWithOptions 还是 applicationDidBecomeActive

So what is the advantage of using begin​Background​Task​With​Expiration​Handler ?

如果你打算使用URLSessionConfiguration.background,就没有这样的优势,你根本不应该使用beginBackgroundTask(expirationHandler:)。你的整个前提(你的第一句话)都是错误的。上传文件 不是 beginBackgroundTask(expirationHandler:) 的好用例。这是 URLSessionConfiguration.background 的一个很好的用例。两者没有任何关系。

此后台任务将使您的应用在用户离开您的应用 3 分钟左右(检查 background​Time​Remaining 实际值)后继续在后台 运行 让您的请求完成.而且,是的,在接近 3 分钟结束时,如果您尚未结束后台任务,将调用超时处理程序。

因此,如果您在应用正常运行期间结束后台任务,则不需要调用此超时闭包。此关闭仅用于任何快速的、最后一分钟的清理,您可能需要在您的应用程序在后台停止 运行 之前执行,因为它在您有机会指示后台任务结束之前超时。这不是为了开始任何新事物,而是为了最后一秒的清理工作。并确保在此超时处理程序中结束后台任务...如果您不结束后台任务,OS 将立即终止您的应用程序,而不仅仅是暂停它。通常,在此超时关闭中您唯一需要做的就是结束后台任务,但如果您需要进行任何其他清理,您可以在这里进行。

不用说,您必须结束您的后台任务(在网络请求完成时,或者在超时处理程序中,如果您的应用还没有机会结束正常流程中的后台任务)。如果不这样做,您的应用不仅会被暂停,还会被终止。

关于假设用户稍后重新启动您的应用程序时会发生什么,您不能假设将调用哪个应用程序委托方法。即使你优雅地结束了后台任务,你也不能保证它不会因为其他原因(例如内存压力)而被抛弃。所以不要假设任何事情。