2

Here's the scenario:

I'm writing a DownloadManager, that allows the user to download, pause, cancel, download all, and pause all. The DownloadManager is a singleton, and uses AFNetworking to download files. It has it's own private managed object context, so that user can freely use other parts of the application (by adding, editing, deleting) core-data objects. I have a core-data entity DownloadInfo that stores the download information i.e. fileURL, fileSize, bytesRead, etc. The DownloadManager updates the download progress in DownloadInfo (one for each file).

I have a DownloadManagerViewController which uses NSFetchedResultsController to show the download status to the user. This download view controller is using the main managed object context.

Now let's say that I have 20 files in the download queue. And let's say that only 3 concurrent downloads are allowed. The download manager should download the file, and show the download progress.

Problem:

The DownloadInfo objects are being updated by the DownloadManager at a very high rate. The DownloadManagerViewController (responsible for showing the download progress) is updating the list using NSFetchedResultsControllerDelegate methods. The result is that a lot is happening in the main queue and application has very poor responsiveness.

How can I fix this? How can I make the application responsive, while showing the download progress?

  1. I don't know how else to communicate that the download status between DownloadManager and DownloadManagerViewController. Is there another/ a better way to do this?

  2. I don't want to use main managed object context in my DownloadManager, for reasons mentioned above. Note, that the DownloadManager is using AFNetworking which is handling the requests asynchronously, but eventually the DownloadInfo objects are updated in the main thread (as a result of the callback methods). Maybe there's a way to handle the downloads and status update operations in a background thread? but how? How will I communicate between the main thread and the background thread i.e. how will I tell the background thread to queue another file for download?

Thanks.

Mustafa
  • 20,504
  • 42
  • 146
  • 209
  • What update info should actually make it to the screen and when? – Wain Jun 29 '13 at 10:07
  • The download progress (i.e. x of y downloaded) along with the file name -- basically. The size of file can vary from a few KBs to MBs, so the screen should refresh every time a new file is added, a file download is completed, a file download starts (from the queue), and update after every second or so. I can compromise of not showing the most current download state i.e. update screen after every 3-5 seconds to show the download progress. – Mustafa Jun 29 '13 at 10:11

2 Answers2

0

Rather than observing every change to the managed object context, consider implementing one or more notifications for the events that you actually want to update the screen. If the notification are being posted from a background thread, be sure to switch back to the main thread before triggering any UI update.

Alternatively, when the FRC delegate methods are called you receive information about what actually changed. You can analyse this and filter out the most frequent and least meaningful changes and just prevent them from resulting in a UI update.

Wain
  • 118,658
  • 15
  • 128
  • 151
0

Have you tried to use Instruments to see what's really going on in your ViewController? Time Profiler is going to tell you where the CPU is spending more time and will help you to identify the root of the problem. Without knowing this, we can't know exactly what performance tweaks you should do.

After using Instruments, if the NSFetchedResultsController is forcing a lot of updates of your VC, you should consider not to read the progress from CoreData. I've seen that a lot of my tables or views spend more time reading from CoreData than performing draws. Guessing that your problem is with CoreData reads, I would try to read progress from an NSMutableDictionary and just update the UI when the downloads pass a certan threshold.

amb
  • 4,798
  • 6
  • 41
  • 68