views:

337

answers:

2

What's the preferred approach for constantly sharing data across threads when using Core Data? I am downloading a large file and want to show progress of the download in a UIProgressBar. The actual download is happening in a background thread created by NSOperation.

The download information (local path, total bytes, bytes received) is modeled as a Core Data managed object, and the actual file is stored in the Documents/ directory. One solution that came to my mind was to create a separate managed object context in the background thread and pass it the objectID and pull it up using the objectWithID: method. Whenever the background thread does a save, the main thread gets a notification and the main context merges those changes and the table view is subsequently updated.

This approach works, but the save can't be done too frequently or the UI freezes up. So the UI is updated after every X KB's of data is received where X has to be at least 500 KB for the UI to be somewhat responsive. Is there a better approach to pass the download progress data to the main thread as it is received?

EDIT: Would using KVO be of any help? If yes, do you know of any good tutorials on the topic?

+2  A: 

I know you already built your own system, but I use ASIHTTPRequest for all my network operations. It is very robust and has tons of goodies like file resuming, saving directly to disk, upload progress monitoring, download progress monitoring, and the kitchen sink. If you dont use it, you can look at the source to see how they do it because the UI never freezes when I use the progress reporting in this framework.

coneybeare
First things first, it's great to be able to upvote! ASIHTTPRequest looks really nice, and I will integrate it into my code. It offers a lot more functionality than my little downloading framework and it's open source :)
Anurag
A: 

Although I am going to use ASIHTTPRequest for my project, it's still good to mention my solution to the problem for completeness. It is kind of obvious, but saving the core data context as frequently as every couple of seconds is a terrible mistake.

Instead, I added a progress delegate to the download operation, which gets update notification on the main thread.

NSNumber bytesDownloaded = [NSNumber numberWithLongLong:[data length]];
[downloadDelegate performSelectorOnMainThread:@selector(updateProgress:) withObject:bytesDownloaded waitUntilDone:NO];

The important thing was to pass the download progress information to the delegate on the main thread. The delegate updates the progress, keeps accumulating changes and either saves when the download completes or at much bigger intervals.

Anurag