NSURLSessionDownloadDelegate Methods on iPhone iOS 10.3.1

I've recently been integrating Background Transfer Service into an application so that the user is able to download files in the background.


I did most of my building/testing on an old iPhone 6 device that was running iOS 9.3.5 (I try to keep my previous device back a version of iOS). Background Transfer Service works great on this device. I am able to put 100+ download tasks into the queue and they all finish and report progress as expected after sending the application into the background and then re-opening the application.


This also appears to work great on a new 5th generation iPad running iOS 10.3.


Where things get weird is on my iPhone 7 Plus which is running iOS 10.3.1. The downloads kick off fine, progress is reported as expected in the didWriteData method, however if I background the application and wait ~10 seconds and re-open the application the progress never catches back up to what progress would have been done in the background and the progress never increments at all (it stays where it was when it was backgrounded). The didFinishDownloading method does end up getting called however it appears to wait until the very end of all the download tasks completions for that method to fire for all of the remaining tasks. So the didWriteData, didFinishDownloading, didCompleteWithError, etc. all happen right at the end in one burst.


I have however had a few instances where my iPhone 7 Plus device running iOS 10.3.1 did show progress after bringing the app back into the foreground however those instances I could could on one hand. More often than not (9 times out of 10) the progress is never reported on this device after re-opening the application.


I am at a bit of a loss and am wondering if there is a known bug we should be looking out for, and if so when we could expect a fix? Or if there are currently any known work arounds. From my testing/debugging I cannot get progress to work in my application on the iPhone 7 Plus running 10.3.1. I also had a co-worker test this as well and they also experienced this.


In fact they went a step further and opened the Netflix application on their 10.3.1 iPhone 7 Plus device and began downloading a movie. Progress incremented as expected, they then backgrounded the application and waited ~20 seconds and re-opened the application, only to find the progress get stuck where it was when the app was initially backgrounded and it never moves. After a given amount of time of the progress not moving the download does eventually finish (the progress indicator disappears) and the Netflix movie is downloaded and able to be played. This is the same behavior I see above in my application.


Any help with this would be greatly appreciated.


Thanks in advance!


Adam

Replies

I’m in two minds about this. On the one hand my suspicion is that, if this problem were widespread, I would have seen lots of reports from other developers about it. On the other hand, your investigation so far seems to strongly indicate that this is a bug in NSURLSession.

Three points:

  • I presume that you’re testing this by running your app from the Home screen rather than from Xcode. See my Testing Background Session Code pinned post for information on why this is important, and for other testing tips.

  • If this is a problem it’s caused by NSURLSession not correctly reconnecting to the session when you come back from being suspended in the background. One interesting test would be to terminate your app to see if things work in that case.

    IMPORTANT Do not test this by force quitting your app. That will cancel all of your requests.

    You can test this by adding a ‘Quit’ button to your app that terminates the app by calling

    exit
    . This is not acceptable in a production app (see QA1561) but it’s handy for testing.
  • Have you tried reproducing this with a small test app? The obvious candidate here is the Simple Background Transfer sample code. If the problem occurs in that sample (even if it requires a few tweaks to get it to reproduce), that’s definitely bugworthy.

Share and Enjoy

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

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

Thank you for the reply.


I can confirm that I was running the applications from the homescreen and not from the Xcode.


I downloaded the Simple Background Trasnfer project you mentioned above and tested a download on the 3 previously mentioned devices and got the same results.


I did go ahead and file a bug with Apple, here is the Problem ID issue #: 32247561


I attached a screen recording of the issue in the bug and also provided a URL of screen recording in the additional notes of the bug in case you are interested in seeing my results.


Thanks again for the help, we'll see where this goes! 🙂

I did go ahead and file a bug with Apple, here is the Problem ID issue #: 32247561

Thanks.

Did you try my

exit
test?

Share and Enjoy

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

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

Not yet - I plan to test that over the weekend. I'll let you know what I find.

Hi Eskimo


I'm seeing the same issue with iOS 11. NSURLSessionDownload delegate methods are not invoked when app resumes from background. Could you please let me know, the status of this issue. If not are there any workarounds?

I don’t know of any current problems with the OS that would cause behaviour like that described above. Most issues like this are caused by folks misunderstanding how background sessions are supposed to work. On the main Core OS > Networking page you’ll find a bunch of pinned posts that explain some of the most common gotchas.

Share and Enjoy

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

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

I'm not sure how I misunderstood how background sessions work?


I posted the example of this happening to me using Apple's source code back in May and filed a bug report but have gotten zero response from Apple.


http://adamzucchi.com/stage/apple/backgroundtransferservice/index.html


https://bugreport.apple.com/web/?problemID=32247561

I wrote:

Most issues like this are caused by folks misunderstanding how background sessions are supposed to work.

adamzucchi wrote:

I'm not sure how I misunderstood how background sessions work?

That post wasn’t in response to anything you wrote, but in response to ramyad’s post from the 2 Nov.

With regards your issue, I haven’t had a chance to look into this in depth but your analysis so far is strong evidence that this is a bug in the OS.

As to workarounds, I’m curious if you can see progress being made by polling the various

NSURLSessionTask
properties (like
countOfBytesReceived
or
countOfBytesSent
), or via KVO-ing properties on the object returned by
progress
.

Share and Enjoy

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

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

I apologize for digging out an old thread for a problem which may well have been resolved since then, but just to add, for Quinn's benefit:


1. I am seeing it too, on iOS 10.3.3. That is: Home button halts the didWriteData method calls (after a short time which I'll call T), tapping on the app icon does not always resume them. (My "not always" is "about half the time").

2. Yes, to cause the problem it is necessary to wait a few seconds after pressing Home, before tapping the app icon.

3. As has been reported, the didFInishDownloading method is called even if the didWriteData calls aren't coming through.


4. Quinn, I have tried the KVO of countOfBytesReceived, as you suggested. Its behaviour is identical to that of didWriteData. If a KVO is triggered, so is the method call. If no method call appears, no KVO appears.



5. NEW: If, after pressing Home, waiting, and tapping the app icon, the didWriteData calls do not happen, then sometimes pressing the Home button will cause a short burst of didWriteData calls. The time that burst lasts is, to my eyes, about the same as the time T which I mentioned in point 1. As if some sort of "send / don't send" toggle missed a beat and thus goes from NO to YES on pressing Home, only to get shut down shortly afterwards because the app is suspended.


This is not a hugely urgent issue for us, in that users have not reported it. Moreover, the quiescence of this thread suggests that the problem, whatever it was, was corrected in iOS 11 – otherwise I would have expected to see more reports. I have not, myself, attempted to reproduce the problem in iOS 11.


Nevertheless, if anybody sees any sign that the problem does occur in iOS 11 then I will go ahead, attempt to reproduce it, and report any results. It would be good to get this sorted out (if it still needs it).

I have the same issue on iOS 12.0. Is there any solution in sight???

I tried polling countOfBytesReceived and it does not update. (this is on iOS 12.0)

Me too - 100% reproducable when running on iPhone 5s with iOS 12.

This issue has always been a problem with iPhone 7 with iOS 11.0 ~ 12.0. The download is complete, but the UI is not updated because the delegate is not called.

The download is complete, but the UI is not updated because the delegate is not called.

I had a quick look at (r. 32247561) and I can’t see any indication of movement on that front. I must stress, however, that this is just a progress issue. You don’t need the

-URLSession:downloadTask:didWriteData:totalBytesWritten:totalBytesExpectedToWrite:
delegate callback for learn about requests completing. The correct way to do that is via the
-URLSession:task:didCompleteWithError:
delegate callback, which, AFAIK, is functioning just fine.

Earlier I suggested two potential workarounds:

  • Polling the

    countOfBytesReceived
    property on the task itself
  • Getting the

    NSProgress
    object from the task and using KVO to observe its various properties (like
    fractionCompleted
    )

Various folks have tried the first and confirmed that it’s not working; I’m curious as to whether anyone has tried the second?

Share and Enjoy

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

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

I have tried to use KVO instead of polling '''countOfByesReceived''' or '''fractionCompleted''' directly. It also does not work.


Also you might say this is only a progress issue, but I personally think that displaying progress for larger files is essential to having a polished and nice to use app. And downloading large files is exactly the use case, where the user will put the app to the background and periodically check for progress.


Displaying download progress seems like a very basic thing and it is a bit disappointing, that there are no workarounds and no progress from Apples side on this 😟