12 Replies
      Latest reply on Jan 17, 2019 1:24 AM by MCKJ
      claurel Level 1 Level 1 (10 points)

        I'm seeing some strange behavior with a background NSURLSession. My app starts a number of download tasks, and everything initially works as expected. There are repeated calls to URLSession:downloadTask:didWriteData:totalBytesWritten:totalBytesExpectedToWrite: and URLSession:downloadTask:didFinishDownloadingToURL. But after suspending the app by pressing the home button and then resuming it, the delegate methods stop getting called regularly. This happens roughly 50% of the time I suspend and resume the app.

         

        If I leave the app active, the downloads do eventually complete. The app delegate's handleEventsForBackgroundURLSession method is called, didFinishDownloadingToURL is called a bunch of times, and then finally the URLSessionDelegate receives the URLSessionDidFinishEventsForBackgroundURLSession call. This is the behavior that I'd expect to see if the app were not active.

         

        While the downloads do eventually complete, there's no way to report progress to the user when the delegate methods aren't called. Has anyone else encountered a problem similar to this?

         

        —Chris

        • Re: NSURLSessionDownloadDelegate methods not called after app resume
          eskimo Apple Staff Apple Staff (11,465 points)

          I’ve seen folks have this problem before because they don’t re-create their NSURLSession background session on app launch.  So this sequence:

          1. Move to background

          2. Suspend

          3. Resume

          4. Move to foreground

          works, because the app never gets terminated, but this sequence:

          1. Move to background

          2. Suspend

          3. OS terminates app

          4. Relaunch

          fails because the app doesn’t re-create the session.  Then, when -application:handleEventsForBackgroundURLSession:completionHandler: gets call the app re-creates its background session and starts getting events again.

          So, my recommendation is that you make sure your app re-creates its NSURLSession background session on launch.

          Share and Enjoy

          Quinn “The Eskimo!”
          Apple Developer Relations, Developer Technical Support, Core OS/Hardware
          let myEmail = "eskimo" + "1" + "@apple.com"

            • Re: NSURLSessionDownloadDelegate methods not called after app resume
              claurel Level 1 Level 1 (10 points)

              It's actually the first sequence that's *not* working.

               

              The session doesn't need to be recreated because the app isn't being terminated. About half the time the app is resumed, the delegate methods are called as expected. A couple suspend/resume cycles generally unsticks the downloader, but that's not ideal for our users.

               

              —Chris

                • Re: NSURLSessionDownloadDelegate methods not called after app resume
                  eskimo Apple Staff Apple Staff (11,465 points)

                  It's actually the first sequence that's not working.

                  I’ve not seen that behaviour before.  I suspect that there’s something specific going on with your app; if this were affecting a lot of apps out there, I’d have seen reports from others.

                  My best guess is that your app is doing something odd that’s causing the background session state to get out of whack.  Perhaps:

                  • Accidentally dropped the completion handler passed to -application:handleEventsForBackgroundURLSession:completionHandler:

                  • Getting a thread stuck in an NSURLSession delegate callback

                  • Or something similar

                  Share and Enjoy

                  Quinn “The Eskimo!”
                  Apple Developer Relations, Developer Technical Support, Core OS/Hardware
                  let myEmail = "eskimo" + "1" + "@apple.com"

                    • Re: NSURLSessionDownloadDelegate methods not called after app resume
                      claurel Level 1 Level 1 (10 points)

                      Thank you for the suggestions. I don't think I'm doing either of those things, but I'll continue to look.

                       

                      The completion hander does not seem to be the problem: after the call to application:handlerEventsForBackgroundURLSession:completionHandler is received, all the didFinishDownloadingToURL calls arrive at once and the app successfully copies the files into place. The problem is that no delegate methods are called before this—it all gets queued into a single burst after all file downloads are complete.

                       

                      —Chris

                      • Re: NSURLSessionDownloadDelegate methods not called after app resume
                        adamzucchi Level 1 Level 1 (0 points)

                        @eskimo - You’re reply to @claurel was the following:

                         

                        My best guess is that your app is doing something odd that’s causing the background session state to get out of whack.  Perhaps:

                        • Accidentally dropped the completion handler passed to -application:handleEventsForBackgroundURLSession:completionHandler:

                        • Getting a thread stuck in an NSURLSession delegate callback

                        • Or something similar

                         

                        Could you explain what you mean by “accidentally dropped the completion handler in point # 1 above?  I believe I’m handling the handleEventsForBackgroundURLSession properly but want to make sure.

                         

                        Also what would cause point # 2 of yours above to occur?

                         

                        Thanks!

                          • Re: NSURLSessionDownloadDelegate methods not called after app resume
                            adamzucchi Level 1 Level 1 (0 points)

                            I have decided to start my own thread on this issue where I can provide more details on what I am personally experiencing with different devces on different versions of iOS: https://forums.developer.apple.com/thread/77666

                              • Re: NSURLSessionDownloadDelegate methods not called after app resume
                                eskimo Apple Staff Apple Staff (11,465 points)

                                Could you explain what you mean by “accidentally dropped the completion handler in point # 1 above?

                                The standard sequence for being resumed in the background for NSURLSession background session events is:

                                1. The system resumes (or relaunches) your app

                                2. If it’s a relaunch, you re-create your background session

                                3. The system calls  -application:handleEventsForBackgroundURLSession:completionHandler: to tell you what session to service

                                4. You save away the completion handler

                                5. The session starts sending you delegate callbacks

                                6. When it’s done it sends -URLSessionDidFinishEventsForBackgroundURLSession:

                                7. You call the completion handler you saved in step 4

                                The gotcha I was specifically referring to relates to steps 4 and 7.  If you fail to save the completion handler (step 4), or fail to call it (step 7), or do something else wrong (like accidentally clear it, or overwrite it), weird things are going to happen.

                                Another gotcha relates to the thread on which you call the completion handler.  It must be called from the main thread.  If you have your NSURLSession delegate set up to run on a secondary thread, you can’t call the completion handler directly from -URLSessionDidFinishEventsForBackgroundURLSession:, but instead must bounce to the main thread to do that job.


                                Also what would cause point # 2 of yours above to occur?

                                Imagine a scenario like this:

                                1. You start a download

                                2. The download completes and your -URLSession:downloadTask:didFinishDownloadingToURL: method is called

                                3. That has to commit the download to your database

                                4. There’s some sort of other problem that causes that commit to deadlock

                                At this point you’re permanently blocked within the delegate callback, which is going to prevent NSURLSession sending your any other delegate callbacks.

                                A similar but harder-to-debug problem relates to delegate callbacks with completion routines.  Consider this:

                                1. You start a download

                                2. The download encounters an authentication challenge

                                3. The system calls your authentication challenge delegate callback (-URLSession:didReceiveChallenge:completionHandler: or -URLSession:task:didReceiveChallenge:completionHandler:)

                                4. That callback fails to call the completion handler

                                Now this request is just stalled; it won’t even time out because all the timeout timers are suspended while waiting for the authentication challenge to be resolved.


                                I’ll respond to your big picture issue on your new thread.

                                Share and Enjoy

                                Quinn “The Eskimo!”
                                Apple Developer Relations, Developer Technical Support, Core OS/Hardware
                                let myEmail = "eskimo" + "1" + "@apple.com"

                      • Re: NSURLSessionDownloadDelegate methods not called after app resume
                        giantguppy Level 1 Level 1 (0 points)

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

                        • Re: NSURLSessionDownloadDelegate methods not called after app resume
                          TimAtBcov Level 1 Level 1 (0 points)

                          I'm finding this problem to be 100% reproducable when running on an iPhone 5s with iOS 12. Has anyone found a resolution?

                          • Re: NSURLSessionDownloadDelegate methods not called after app resume
                            MCKJ Level 1 Level 1 (0 points)

                            I have get the same problem on iOS 12, Has anyone konw about what is going on? There is my simple code project ( https://github.com/hwzss/BackgroundSessionProblemExample )