iosnsurlsessionnsurlsessionuploadtask

NSURLSessionUploadTask get response data


I have some misunderstanding in using NSURLSession framework, that's why I decided to write small app from scratch without AFFramework/Alamofire.

I have an API that requires following steps to upload file:

  1. POST file data
  2. Get response (JSON)
  3. Post some json fields to api/save

I have a background session with such config:

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

I've implemented 2 methods:

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

where I aggregate all data

and

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

where I tranform this data to response object. This response object if VERY important for me.

Everything works fine, while app is in foreground, but I have problems in background.

Case 1

App crashed right after I've started to upload data. According to WWDC I need to implement

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

and call this handler in didCompleteWithError method. But before calling this method I need to call api/save with data from upload response. How can I get this data?

Case 2

Mostly similar case. User stops app while upload is in progress. Than loads app in few seconds, while session works with my task. Now session calls didReceiveData, but of course, some of data is missing. What should I do in such case? How to restore response data?


Solution

  • You don't mention implementing URLSessionDidFinishEventsForBackgroundURLSession (a NSURLSessionDelegate method). You really want to implement that, too. The basic process is:

    If you're doing all of that, when the background session is restarted, the didReceiveData calls will come in with the responses to your various uploads.

    I just did a quick test, uploading five 20mb images and immediately terminating the app. Then, even though the app wasn't running, I watched the five files slowly show up on my server (obviously handled by the daemon process). When all five were done, by app was transparently restarted in the background, the handleEventsForBackgroundURLSession was called (which restarted the session), it let all of the didReceiveData calls quickly get called, and when that was done, URLSessionDidFinishEventsForBackgroundURLSession was called and my app only then called the saved completion handler.

    In terms of why this isn't working for you, there's not enough to diagnose the problem. Possibilities include:

    It's hard to say, but I suspect that there's something buried inside your implementation that isn't quite right and it's hard to say what it is on the basis of the information provided (assuming it isn't one of the above points). Unfortunately, debugging this background sessions is vexingly complicated because when the app terminates, it is no longer attached to the debugger, so you can't easily debug what happens after the app is restarted automatically by iOS). Personally, I either NSLog messages and just watch the device console (as well as watching what appears on the server), or I build some persistent logging mechanism into the app itself.