Search code examples
iosswiftnsurlsessiondownloadtask

NSURLSessionDownloadTask continues download while suspended


I'm using NSURLSessionDownloadTask to download files. At one point in the application it is necessary to pause the download for a short time and then resume it. I tried using the suspend method for pausing the download but the task continuous to download. Apple documentation for NSURLSessionTask's method suspend states:

A task, while suspended, produces no network traffic and is not subject to timeouts. A download task can continue transferring data at a later time. All other tasks must start over when resumed.

This seems to indicate that what I'm doing is right, but the result is not as expected. I was able to reproduce it with the following code in the Playground.

import UIKit

let backgroundSessionConfiguration = URLSessionConfiguration.background(withIdentifier: "some-identifier")
let backgroundSession = Foundation.URLSession(configuration: backgroundSessionConfiguration, delegate: nil, delegateQueue: nil)

let request = URLRequest(url: URL(string: "http://google.com")!)
let task = backgroundSession.downloadTask(with: request)

task.state.rawValue

task.resume()
task.state.rawValue

task.suspend()
task.state.rawValue

sleep(10)

task.state.rawValue

The expected result for task states would be 1, 0, 1, 1 (0 - downloading, 1 - suspended, 2 - cancelled, 3 - done). Actual result is 1, 0, 1, 3. This means that although the task is suspended it still continues to download and marks itself done once the download is finished.

The setup in the app is more complicated and the task states cannot always be replicated (in the Playground the results seem always the same) but the result after suspending the task is always that the file is successfully downloaded (including that the progress callback is called).

The question: Am I doing something wrong? Have I misunderstood the Apple docs and it's not possible to pause a download task this way?

My first intuition when faced with this issue in the app was that I was calling resume somewhere else that resulted in the download to continue, but this does not seem to be the case after debugging the code + the Playground findings support this as well.


Solution

  • Probably not the answer you're looking for, but an Apple Dev Relations representative has confirmed in their dev forums that background downloads can in some situations not be really suspended by using suspend:

    [...] a suspended task can still be active on the wire; all that the suspend does is prevent it making progress internally, issuing callbacks, and so on.

    They go on by suggesting to use cancel(byProducingResumeData:) instead:

    if you're implementing a long-term pause (for example, the user wants to pause a download), you'd be better off calling -cancelByProducingResumeData:.