views:

766

answers:

2

I've a Core Data application. In the producer thread, I pull data from a web service and store it in my object and call save. My consumer object is a table view controller that displays the same. However, the app crashes and I get NSFetchedResultsController Error: expected to find object (entity: FeedEntry; id: 0xf46f40 ; data: ) in section (null) for deletion

on the console. When I debug it, everything works fine. So I understood that it's like a race issue.

How is these kind of problem solved? What's the best way to design a producer-consumer app with core-data?

A: 

Core Data is generally not thread safe. My preference would be to do minimal work on the background thread, and pass the data needed to create Core Data entities to the main thread once you've retrieved it from your web service. However, take a look at this document. There are some strategies for using Core Data across threads if you need to.

Marc Charbonneau
"Core Data is generally not thread safe" is rather misleading. If you create a context for each thread (or each operation; contexts are pretty lightweight) the rest of the Core Data framework takes care of pretty much everything else (all you have to do is handle NSManagedObjectContextDidSaveNotifications as described above).
hatfinch
+8  A: 

If you are targeting Leopard or later, Apple has made things a touch easier.

In your producer thread create a MOC with the same PSC as the MOC in your main thread. You can pull objects from your webservice in this thread, create the new objects, and save them as normal.

In your consumer thread, add your controller as an observer for the NSManagedObjectContextDidSaveNotification. Your callback should look something like:

- (void) managedObjectContextDidSave:(NSNotification *)notification
{
  NSManagedObjectContext *managedObjectContext = [notification object];
  if(managedObjectContext != self.managedObjectContext)
    [self.managedObjectContext mergeChangesFromContextDidSaveNotification:notification];
}

In this way, objects saved in the producer thread will be automatically pulled in your consumer thread.

sbooth
Thanks sbooth... Your answer was perfect...For others,To subscribe to the NSManagedObjectContextDidSaveNotification, add the following code... [[NSNotificationCenter defaultCenter] addObserver:appDelegate selector:@selector(managedObjectContextDidSave:) name:NSManagedObjectContextDidSaveNotification object:self.managedObjectContext];
Mugunth Kumar