3

I need to pause download tasks and resume it even after app restarted. But I am unsure which method should I use, suspend or cancelByProducingResumeData.

With cancelByProducingResumeData I can get the partially downloaded data and recreate download task with it. However I have to manually manage the data, save it to file, read it back, and recreate the task and ensure the new task doesn't fail.

With suspend, I can pause and resume the download task. But can I resume this task after the app is restarted? I am using background session so tasks are preserved across restart.

cancelByProducingResumeData have requirements for it to work, does those requirements also applies to suspend/resume? Or suspend/resume is only mean for "temporarily suspends a task" as the document said?

Bryan Chen
  • 45,816
  • 18
  • 112
  • 143

2 Answers2

3

You're overthinking the problem. The "resume data" for a download task is not the data that the task has received up to that point. It is a tiny blob of bookkeeping data—the sort of thing that you'd typically throw into an array in NSUserDefaults.

With that said, to answer the original question, a task is only valid within the context of a session. So for a foreground session, once your app quits, the session ceases to exist, so it is no longer possible to gain access to tasks in that session. Therefore, it is not possible to resume a suspended task after you relaunch the app because the task no longer exists (because its session no longer exists).

For a background session, you'd pretty much have to ask somebody on the Foundation Networking team to get an answer to that one, because it depends on the extent to which you can recreate a session after the fact. However, my guess is that it probably won't work there, either, and if it does, you should consider it unsupported.

dgatwood
  • 10,129
  • 1
  • 28
  • 49
  • Are you claiming that the "resume data" is not usable between app launches? Is that documented somewhere? – jtbandes May 18 '16 at 23:03
  • No, not at all. The data that the task has received up to that point is silently stored in a file on disk by the download task. The resume data just tells the new task where to find it. That's why it is such a small blob of data. – dgatwood May 18 '16 at 23:14
  • OK, I was confused by reading too quickly — by *"it is not possible to resume a suspended task after you relaunch the app"* you really meant `suspend()`ed, not `cancelByProducingResumeData`, which I believe does serve OP's needs. – jtbandes May 18 '16 at 23:16
  • Correct. Canceling a task does not suspend it. It cancels it. :-) – dgatwood May 18 '16 at 23:29
  • I always thought resume data is the partially downloaded data + meta data, but I just checked it looks like task serialised with XML format. Thanks for that info. – Bryan Chen May 18 '16 at 23:39
  • Also worth noting that in some versions of iOS 8, the sandbox path can change on relaunches, requiring a workaround: https://stackoverflow.com/questions/28360750/nsurlsession-with-invalid-resume-data – dgatwood Sep 27 '18 at 06:32
2

After some research on apple developer forms, I found this

Tasks suspension is rarely used and, when it is, it's mostly used to temporarily disable callbacks as part of some sort of concurrency control system. That's because 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.

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

So suspend may not actually stop downloading and I should use cancelByProducingResumeData: for long-term pause.

Community
  • 1
  • 1
Bryan Chen
  • 45,816
  • 18
  • 112
  • 143
  • That's not strictly true. At some point, the TCP socket's receive buffer should fill up because of nobody reading from it, at which poing the remote host should stop sending data. With that said, it probably doesn't buy you much unless you're using it to pause a bulk transfer so you can do something more time-critical. – dgatwood May 18 '16 at 23:32