Ios NSURLSessionPloadTask获取响应数据

Ios NSURLSessionPloadTask获取响应数据,ios,nsurlsession,nsurlsessionuploadtask,Ios,Nsurlsession,Nsurlsessionuploadtask,在使用NSURLSessionframework时,我有一些误解,这就是为什么我决定从头开始编写小型应用程序,而不使用AFFramework/Alamofire 我有一个API,需要执行以下步骤才能上载文件: 后置文件数据 获取响应(JSON) 将一些json字段发布到api/save 我有这样一个配置的后台会话: let configuration = NSURLSessionConfiguration.backgroundSessionConfigurationWithIdentifier(

在使用
NSURLSession
framework时,我有一些误解,这就是为什么我决定从头开始编写小型应用程序,而不使用AFFramework/Alamofire

我有一个API,需要执行以下步骤才能上载文件:

  • 后置文件数据
  • 获取响应(JSON)
  • 将一些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)
    
    在这里我聚集了所有的数据

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

    一切正常,虽然应用程序在前台,但我在后台有问题

    案例1

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

    func application(application: UIApplication, handleEventsForBackgroundURLSession identifier: String, completionHandler: () -> Void)
    
    并在
    didpletewherror
    方法中调用此处理程序。但在调用此方法之前,我需要使用上传响应中的数据调用
    api/save
    。 如何获取这些数据

    案例2


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

    您没有提到实现
    urlsessiondifinisheventsforbackgroundurlsession
    (一种
    nsurlsessionelegate
    方法)。你真的也想实现这一点。基本过程是:

    • 在应用程序代表的
      handleEventsForBackgroundURLSession
      中,您应该:

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

    如果您正在执行所有这些操作,那么当后台会话重新启动时,
    didReceiveData
    调用将附带对各种上载的响应

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

    至于这对你不起作用的原因,还不足以诊断问题。可能性包括:

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

    • 可能在调用
      handleEventsForBackgroundURLSession
      时您没有重新启动会话

    • 可能您调用提供的完成处理程序太早(即调用
      urlsessiondifinisheventsforbackgroundurlsession
      之前)


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

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

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

    来源:

    谢谢你的精彩解释。我把你的答案标为“正确”,因为(我相信)它能解决别人的问题。然而,我实现了
    urlsessiondifinisheventsforbackgroundurlsession
    ,但运气不好。我重新启动了bg会话,得到了
    URLSession(会话:NSURLSession,数据任务:NSURLSessionDataTask,didReceiveData:NSData)
    我得到了以下数据:
    session:dataTask:{taskIdentifier:1}数据:0
    ,当我试图追加数据时,它会使我的应用程序崩溃
    func application(application: UIApplication, handleEventsForBackgroundURLSession identifier: String, completionHandler: () -> Void)