views:

978

answers:

1

I'm passing some NSManagedObject data between two threads using NSOperationQueue with concurrency level to max of 1 and I'd like some suggestions on whether I'm doing this correctly.

Since NSManagedObject is not thread-safe, I'm sending in the NSManagedObjectID from ThreadA (main thread) to ThreadB via an NSOperation derived class. The general work flow:

ThreadA (main thread):

  • creates NSPersistentStoreCoordinator
  • creates main NSManagedObjectContext(1)
  • creates NSManagedObjectContext(2) for use in workerThread

  • creates MyNSOperationItem, passes along NSManagedObjectContext and adds MyNSOperationItem to NSOperationQueue

ThreadB (NSOperationQueue's thread):

  • NSOperation derived class will retrieve data from the persistent
    store using the supplied objectID.

My NSOperation class looks like this:

@interface MyNSOperationItem: NSOperation
{
    // MyNSOperationItem is created in thread1 and MOC will be 
    // set on creation
    NSManagedObjectContext   *threadedMOC;

    NSManagedObjectID        *workItemObjectID;
}
@end

So is it okay for my NSOperation derived class to have a reference to NSManagedObjectContext or should I store the second NSManagedObjectContext elsewhere? Since this is a queue, numerous instances of MyNSOperationItem will have been created, each of them pointing to the same NSManagedObjectContext.

+2  A: 

I think this should give you all you need:

http://developer.apple.com/mac/libra...reData/Articles/cdMultiThreading.html

If you need to offload the fetch to a background thread, here is a little tip from the document I referenced above:

Fetching in a Background Thread

One of the simplest multi-threading techniques you can use with Core Data to improve application responsiveness is to execute a fetch request on a background thread. (Note that this technique is only useful if you are using an SQLite store, since data from binary and XML stores is read into memory immediately on open.) This means that if a fetch is complicated or returns a large amount of data, you can return control to the user and display results as they arrive. For an example of how to do this, see the BackgroundFetching example in /Developer/Examples/CoreData/.

You use two managed object contexts associated with a single persistent store coordinator. You fetch in one managed object context on a background thread, and pass the object IDs of the fetched objects to another thread. In the second thread (typically the application's main thread, so that you can then display the results), you use the second context to fault in objects with those object IDs (you use objectWithID: to instantiate the object).

Matt Long
The link referenced a sample app called 'BackgroundFetching' in the '/Developer/Examples/CoreData' -- no such directory exists on my machine. Any ideas on where to find that sample?
Alexi Groove
Yep. You're right. And it doesn't appear to be available on the dev site any more either. Not sure what the deal is. You could file a documentation bug with Apple that points out the out of date information. Maybe they'll update it with a new path or link. Then again, maybe they'll update it and remove the path/link altogether. Sorry about that.
Matt Long