我按照本教程在后台下载文件与 URLSessionDownloadTask
和这个苹果文档在后台下载文件
我尝试设置,因为我们有一个长时间运行的 API
let config = URLSessionConfiguration.background(withIdentifier: "(Bundle.main.bundleIdentifier!).background")
config.timeoutIntervalForRequest = 120
config.timeoutIntervalForResource = 180
但我遇到了这个奇怪的问题:
如果服务器没有响应任何数据,这意味着
func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64)
根本不会被召唤。
该应用程序将终止以前的请求,并每 66 秒重试一个新请求。我不知道这个数字是从哪里来的,但从我的实验来看,它大约是 66 秒
如果我将timeoutIntervalForRequest = 10
设置得足够确定,应用程序将每 10 秒重试一次请求,但任何将其设置为 66 秒以上的尝试都不起作用
不确定是否有人遇到相同的问题并找到了解决方案。
只需 1 个注释:当达到 180 秒并且应用程序停止重试新请求时,整个过程将超时
首先,这是一个错误。 请 bugreport.apple.com 提交。 不应像这样忽略超时。 当然,这很有可能是一个电源管理问题,不会得到解决,所以我不会屏住呼吸。
其次,您正在以一种几乎可以保证导致问题的方式解决问题,即使超时错误已修复。 当然,您的服务器没有发回任何字节以保持连接活动的事实也是iOS设备断开连接的原因,但是即使您更改它并使其每五秒一次发送一个字节的虚假标头,直到数据准备就绪,您仍然会遇到问题。
基本上,在移动设备上,您真的不应该出于任何原因保持长时间运行的连接与远程服务器保持打开状态。 它大量浪费电池来保持Wi-Fi无线电持续打开,更不用说蜂窝无线电了,更糟糕的是,当用户超出范围,切换蜂窝基站或以其他方式暂时失去连接时,连接可能随时失败。 网络是垃圾——蜂窝网络更是如此。
对于长时间运行的服务器处理,更好的方法是异步执行:
- 向服务器发出请求。
- 让服务器发回与请求关联的唯一标识符,以及(可选(估计完成时间。
- 等到估计的完成时间,然后询问服务器情况如何(提供该唯一标识符(。
- 继续定期轮询服务器,直到服务器指出任务已完成(或失败(。
- 当服务器说任务已完成时,发出请求以检索结果,然后发出请求以释放已完成的结果。
- 使用 cron 作业或类似作业定期清理服务器上未收集的旧结果。
这种方法避免了使无线电保持热,除了轮询请求两侧的几秒钟,并且它使超时问题完全没有意义。