NSURLSessionUploadTask获取响应数据

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

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

  1. POST文件数据
  2. 获取响应(JSON)
  3. 张贴一些JSON领域的api/save

我有这样的configuration后台会话:

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

我已经实现了2个方法:

 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) 

并在didCompleteWithError方法中调用此处理程序。 但在调用这个方法之前,我需要调用api/save从上传响应的数据。 我怎样才能得到这些数据?

案例2

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

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

  • 在应用程序委托的handleEventsForBackgroundURLSession ,您应该:

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

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

我只是做了一个快速testing,上传五个20MB的图像,并立即终止应用程序。 然后,即使应用程序没有运行,我看到五个文件缓慢地显示在我的服务器上(显然是由守护进程处理的)。 当所有五个都完成后,通过应用程序在后台透明地重新启动, handleEventsForBackgroundURLSession被调用(重新启动会话),它让所有的didReceiveData调用很快被调用,当完成时, URLSessionDidFinishEventsForBackgroundURLSession被调用,我的应用程序然后调用保存的完成处理程序。

关于为什么这不适合你,没有足够的诊断问题。 可能性包括:

  • 也许你不适当地终止了应用程序。 你不能杀死应用程序,双击主页button,并终止在那里的应用程序; 你必须让它自然终止,或者为了诊断/testing的目的,我强迫它通过在代码中调用exit(0)来终止。

  • handleEventsForBackgroundURLSession被调用时,可能你没有重新启动会话。

  • 也许你过早地调用了提供的完成处理程序(即在URLSessionDidFinishEventsForBackgroundURLSession之前)。

这很难说,但是我怀疑你的实现中埋藏着一些不太正确的东西,根据所提供的信息(假设它不是上面提到的),很难说这是什么东西。 不幸的是,debugging这个后台会话是非常复杂的,因为当应用程序终止时,它不再附加到debugging器,所以你不能轻易地debuggingiOS自动重启应用程序后会发生什么。 就我个人而言,我要么NSLog消息,只是看设备控制台(以及观看服务器上显示的内容),或者我build立了一些持久的日志机制进入应用程序本身。

为了testing后台会话代码,build议在真实设备上进行testing。 在编写使用NSURLSession后台会话支持的应用程序时,很容易被开发过程中的三个不明显的工件所困惑:

  • 当您从Xcode运行您的应用程序时,Xcode会将该应用程序安装在新的容器中,这意味着您的应用程序的path发生了变化。 这可能会混淆NSURLSession的后台会话支持。 注意 :iOS 9中解决了这个问题, 如果遇到NSURLSession在iOS 9或更高版本中未处理容器path更改的问题,请提交一个错误。
  • Xcode的debugging可以防止系统挂起你的应用程序。 因此,如果您从Xcode运行应用程序,或者在启动后一段时间附加到该过程,然后将您的应用程序移到后台,那么在系统将暂停它的情况下,您的应用程序将继续执行。
  • 同样,iOS模拟器不能准确地模拟应用程序的挂起和恢复; 这已经在过去,但它不适用于iOS 8或iOS 9模拟器。

来源: 苹果开发者论坛