1

I am working with Xamarin.iOS and implementing a Downloadmanager.

I have found a tutorial on how to implement a DownloadManager in swift, lead by that tutorial I have transcribed the logic written in swift into C#. The DownloadManager works and queues Operations and executes them. The only issue I am facing is the transition of the App to suspended mode. The behavior of the queue is not so deterministic. Sometimes all queued operations are executed and sometimes the app stops the execution.

Use Case 1: I start the file sync and lock the iPad. Most of the time the queued operations are executed. But sometimes when I unlock the iPad the Application is send to the background and I have to double tap the home button to return to the Application, in this case the file sync has stopped somehow in the middle of execution.

Use Case 2: I start the file sync and send the app to the background. The same behavior like in the previous use case. Sometimes all operations are executed and sometimes the operations stops.

Use Case 3: The customer starts the sync and leaves the iPad unattended after some time he comes back and the Sync is not finished and the Application is in the background. In average about 70% of the sync is done.

For the implementation I have used a "NSOperationQueue" that has "DownloadOperation" as elements. The "DownloadOperation" are just a wrapped of the NSOperation object with the execution set to "Asynchronous".

Possible Questions

  • I am not sure what happens to the "NSOperationQueue" when the Application changes states?
  • Is the usage of the "NSOperationQueue" the "right" way to go with the implementation of a DownloadManager?
  • Are there any common tips for the optimisation of the execution of the "NSOperationQueue" and/or the "NSOperation"

Looking forward to the discussion.

P.S. I have enabled "Background Modes" and "Background Fetch"

  • I think you just need a cancellation trigger, you can do this for Tasks, not sure about NSOperationQueues. If it's possible to implement a cancallation trigger, you'll know if the operation stops, and when the app reloads be able to handle it accordingly. – JoeTomks Sep 04 '17 at 14:58
  • @Digitalsa1nt I do not want to cancel the operations, I want them to continue their execution after the app has terminated. That was the reason for the usage of the OperationQueue and NSUrlSession with the NSOperations. But thank you for your comment I hope someone has a clue for this problem. – Igor Jakovljevic Sep 11 '17 at 07:47
  • You can't keep code running indefinately after iOS has terminated your application. Or should I say it's against apples guidelines to do so. Hopefully someone will find a work around for you. :) – JoeTomks Sep 11 '17 at 07:48
  • 1
    @Digitalsa1nt Hmm it is somehow confusing, because in the guidelines on how to implement a download manager they say the download/upload operations should be handled by the system and that the way to implement these things is to use the OperationQueue and NSUrlSession. I mean would be nice how providers like DropBox or gDrive implement these things, because they have to sync their data. I also hope to find something. Have a nice day :D – Igor Jakovljevic Sep 11 '17 at 07:52

1 Answers1

0

According to your description, I suppose you used the NSURLConnection to execute background download which is deprecated. Also, Background Fetch is for small amounts of content and it will be active opportunistically, which is not appropriate for your scenario:

Fetching Small Amounts of Content Opportunistically

Apps that need to check for new content periodically can ask the system to wake them up so that they can initiate a fetch operation for that content.

So, you could switch to use NSURLSession which is officially recommended for downloading content in background. To configure a background session, the download process will be still ongoing in case the app is suspended or terminated(except user has forced quite the app). Refer to this Apple documentation:

Downloading Content in the Background

When downloading files, apps should use an NSURLSession object to start the downloads so that the system can take control of the download process in case the app is suspended or terminated. When you configure an NSURLSession object for background transfers, the system manages those transfers in a separate process and reports status back to your app in the usual way. If your app is terminated while transfers are ongoing, the system continues the transfers in the background and launches your app (as appropriate) when the transfers finish or when one or more tasks need your app’s attention.

...

If tasks have not yet finished and the system terminates your app, the system automatically continues managing the tasks in the background. If the user terminates your app, the system cancels any pending tasks.

About how to create a download manager for background via NSURLSession, you can refer to:

Blog with swift: Downloading files in background with URLSessionDownloadTask

Xamarin guides: Walkthrough - Using Background Transfer Service and NSURLSession

I think you need to download multiple files in background, here's a good guide for you: Downloading multiple files in batches in iOS .

Community
  • 1
  • 1
Kevin Li
  • 2,258
  • 1
  • 9
  • 18
  • I have implemented the whole Manager with "NSURLSession". In short I create a NSOperationQueue with NSOperations where each operation has a NSURLSessionDownloadTask that is created by the base NSURLSession of the DownloadManager. This should enable the download of multiple files even when the app is suspended. I have used this post as a reference -- > [link](https://stackoverflow.com/questions/32322386/how-to-download-multiple-files-sequentially-using-nsurlsession-downloadtask-in-s) – Igor Jakovljevic Sep 05 '17 at 11:42