我遵循了本教程Downloading files in background with URLSessionDownloadTask

这个苹果文件Downloading Files in the Background

我尝试设置是因为我们的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)
根本不会被 call 。

该应用程序将终止先前的请求,并每66秒重试一次新请求。我不知道这个数字来自哪里,但是根据我的实验,大约是66秒

如果我足够确定地设置了timeoutIntervalForRequest = 10,则该应用将每10秒重试一次该请求,但是任何将其设置为66秒以上的尝试均无效

不知道是否有人遇到相同的问题并找到了解决方案。

仅需注意1条:达到180秒时,整个操作将超时,并且该应用程序停止重试新请求

最佳答案

首先,这是一个错误。请提交到bugreport.apple.com。超时不应该那样被忽略。当然,这是电源管理问题并且不会得到解决的可能性很大,因此我不会屏息。

其次,即使超时错误已修复,您也可以通过一定的方式来解决问题。您的服务器没有发回任何字节以保持连接正常的事实当然是iOS设备断开连接的原因,但是即使您进行了更改并使其每次每次都发送一个伪造的头一个字节在数据准备好五秒钟之前,您仍然会遇到问题。

基本上,在移动设备上,出于任何原因,您实际上都不应该保持与远程服务器的长时间运行的连接打开。连续浪费Wi-Fi无线电,大大浪费了电池,更不用说蜂窝无线电了,更糟糕的是,当用户走出范围,切换蜂窝站点或暂时失去连接时,该连接随时可能失败。网络简直是垃圾,蜂窝网络则是如此。

对于长时间运行的服务器处理,更好的方法是异步进行处理:

  • 向服务器发出请求。
  • 让服务器向您发送与请求关联的唯一标识符,以及可选的估计完成时间。
  • 等待直到估计的完成时间,然后询问服务器运行情况(提供唯一标识符)。
  • 继续定期轮询服务器,直到服务器说任务完成(或失败)为止。
  • 服务器说任务完成时,发出请求以检索结果,然后发出请求以释放完成的结果。
  • 使用cron作业或类似作业定期清理服务器上未收集的旧结果。

  • 这种方法避免了在轮询请求的两边仅保持几秒钟的时间之外都保持无线电处于高温状态,这使超时问题完全没有意义。

    关于ios - NSURLSessionConfiguration的timeoutIntervalForRequest无法与后台URLSession一起使用,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/51062721/

    10-13 03:51