Confusion about background download

I am confused with the background download using URLSession. Reading the blogs on the Internet, I have got many kinds of using background download and I don't know which one is the corrent way and now I have some doubt.


Precodition: schedule one task at a time.

1. Invoke the completionHandler or be killed.


I know that if I want to download files one by one, I should hold the completionHandler myself and invoke it whenever all my tasks are added and finished, or the app will be killed. However sometimes my app will be killed once simply one of my tasks is finished. Because I don't know the exact time when I will invoke the completion handler because of the network status and the amount of tasks, nor do the OS knows these. So how the OS thinks that my app does not invoke the handler and should be killed and kills it? I don't know why my app will be killed so fast.

2. Where to add a new task.


Till now, I add new task when my current task is finished in the delegate method:


- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location;


I have read some article that some developers add new task in:


- (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session


But I think that adding task in the latter is more complex because if the current task is finished while the app is in foreground, this method will not be called so the new tasks will not be added. So which one the the right way? Or should I add task in both of the methods above?


3. No response if not run by xcode


Bellow occur in foreground. Sometimes, I run my app from the home screen and try downloading files, but I can't receive any response. So I try to debug it and run it with xcode, It begins to download normally and I can receive data now... If I stop it and reopen it from the home screen, it fails to receive data again... I don't know when this will occur but this indeed occur. I know that low power and network status will affect it but both of these seem not bad...


Could anyone helps ?? I want to know what is the right way to download with URLSession...

Replies

Looking at the big picture, when working in a background session the whole strategy of starting task N+1 in response to the completion of task N is flawed. You will quickly invoke the ire of NSURLSession’s resume rate limiter. I strongly encourage you to move away from that model.

1. Invoke the completionHandler or be killed.

Holding on to the completion handler passed to

-application:handleEventsForBackgroundURLSession:completionHandler:
for a long time is a really bad idea. That completion handler does two things:
  • It takes a snapshot of your UI, for the benefit of the multitasking UI.

  • It ends an background task assertion that prevents the system from suspending your app.

This last point is critical. The background task assertion is equivalent to a UIApplication background task. If you don’t end it quickly, you will be killed by the system watchdog.

2. Where to add a new task.

From an NSURLSession perspective it does not matter; this is really between you and your code.

And yes, your point about

-URLSessionDidFinishEventsForBackgroundURLSession:
only being called when your app is resumed in the background to handle NSURLSession events is quite valid.

3. No response if not run by xcode

It’s hard to say what’s going on here based on the info you’ve posted. My general advice on this topic is in the Testing Background Session Code pinned post.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Thanks! I think I'd better try changing the model to pass all the tasks to the background session first. I have one more question that can the HTTPMaximumConnectionsPerHost limits the concurrency? I find that even if I set HTTPMaximumConnectionsPerHost = 1, several files are still being downloaded simultaneously and all the files are from the same host..

I have one more question that can the HTTPMaximumConnectionsPerHost limits the concurrency?

There’s another thread that’s discussing this right now. You’re not the only person seeing it but I’m not able to reproduce it myself.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"