NSURLSessionUploadTask获取响应数据



我在使用NSURLSession框架时有一些误解,这就是为什么我决定在没有AFFramework/Alamofire的情况下从头开始编写小型应用程序。

我有一个API,需要以下步骤上传文件:

  1. POST文件数据
  2. 获取响应(JSON)
  3. 将一些json字段发布到api/save

我有一个后台会话,配置如下:

let configuration = NSURLSessionConfiguration.backgroundSessionConfigurationWithIdentifier("myBackground")
let session = NSURLSession(configuration: configuration, delegate: self, delegateQueue: nil)

我已经实现了两种方法:

func URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, didReceiveData data: NSData)

其中我聚合所有数据

func URLSession(session: NSURLSession, task: NSURLSessionTask, didCompleteWithError error: NSError?)

在那里我将这些数据转换为响应对象。这个响应对象对我来说非常重要。

一切都很好,虽然应用程序在前台,但我在后台遇到了问题。

案例1

我刚开始上传数据,应用程序就崩溃了。根据WWDC,我需要实施

func application(application: UIApplication, handleEventsForBackgroundURLSession identifier: String, completionHandler: () -> Void)

并在CCD_ 3方法中调用该处理程序。但在调用此方法之前,我需要使用上传响应中的数据调用api/save。如何获取这些数据?

情况2

大多数情况类似。用户在上传过程中停止应用程序。Than在几秒钟内加载应用程序,而会话处理我的任务。现在会话调用didReceiveData,但当然,有些数据丢失了。在这种情况下我该怎么办?如何恢复响应数据?

您没有提到实现URLSessionDidFinishEventsForBackgroundURLSession(NSURLSessionDelegate方法)。你真的也想实现这一点。基本流程是:

  • 应用程序内代理的handleEventsForBackgroundURLSession,您应该:

    • 启动后台NSURLSession(它将开始接收与所有上传相关联的委托方法调用);以及
    • 保存完成处理程序(但不要调用它)
  • 然后,在URLSessionDidFinishEventsForBackgroundURLSession中(处理完所有响应后),调用保存在handleEventsForBackgroundURLSession中的完成处理程序。(确保将其发送到主队列。)

如果您正在执行所有这些操作,当后台会话重新启动时,didReceiveData调用将对您的各种上传做出响应。

我只是做了一个快速测试,上传了五张20mb的图片,并立即终止了应用程序。然后,即使应用程序没有运行,我也看到这五个文件慢慢出现在我的服务器上(显然是由守护进程处理的)。当这五个都完成后,by应用程序在后台透明地重新启动,handleEventsForBackgroundURLSession被调用(它重新启动了会话),它让所有didReceiveData调用快速被调用,当这一切完成后,URLSessionDidFinishEventsForBackgroundURLSession被调用,我的应用程序只调用了保存的完成处理程序。

就为什么这对你不起作用而言,没有足够的信息来诊断问题。可能性包括:

  • 也许您不恰当地终止了应用程序。你不能通过双击主页按钮并在那里终止应用程序来杀死应用程序;您必须让它自己自然地终止,或者出于诊断/测试目的,我通过在代码中调用exit(0)来强制它终止。

  • 也许您在调用handleEventsForBackgroundURLSession时没有重新启动会话。

  • 可能您调用所提供的完成处理程序过快(即在调用URLSessionDidFinishEventsForBackgroundURLSession之前)。

这很难说,但我怀疑您的实现中隐藏着一些不太正确的东西,而且很难根据提供的信息(假设它不是上述要点之一)说出它是什么。不幸的是,调试这个后台会话非常复杂,因为当应用程序终止时,它不再连接到调试器,因此您无法轻松调试iOS自动重启应用程序后发生的事情)。就我个人而言,我要么NSLog消息,只看设备控制台(以及服务器上出现的内容),要么在应用程序本身中构建一些持久的日志记录机制。

对于测试后台会话代码,建议在真实设备上进行测试。当编写一个使用NSURLSession后台会话支持的应用程序时,很容易被开发过程中的三个不明显的工件所混淆:

  • 当您从Xcode运行应用程序时,Xcode会将应用程序安装在一个新容器中,这意味着应用程序的路径会更改。这可能会混淆NSURLSession的后台会话支持。注意:此问题已在iOS 9中修复;如果您在iOS 9或更高版本中遇到NSURLSession无法处理容器路径更改的问题,请提交一个错误
  • Xcode的调试可防止系统挂起您的应用程序。因此,如果你从Xcode运行你的应用程序,或者在启动后一段时间连接到进程,然后将应用程序移到后台,那么在系统本来会暂停的情况下,你的应用将继续执行
  • 同样,iOS模拟器也不能准确模拟应用程序暂停和恢复;这在过去是有效的,但在iOS 8或iOS 9模拟器中不起作用

来源:苹果开发者论坛

相关内容

  • 没有找到相关文章

最新更新