Core Data multi thread application Core Data multi thread application ios ios

Core Data multi thread application


The Apple Concurrency with Core Data documentation is the place to start. Read it really carefully... I was bitten many times by my misunderstandings!

Basic rules are:

  1. Use one NSPersistentStoreCoordinator per program. You don't need them per thread.
  2. Create one NSManagedObjectContext per thread.
  3. Never pass an NSManagedObject on a thread to the other thread.
  4. Instead, get the object IDs via -objectID and pass it to the other thread.

More rules:

  1. Make sure you save the object into the store before getting the object ID. Until saved, they're temporary, and you can't access them from another thread.
  2. And beware of the merge policies if you make changes to the managed objects from more than one thread.
  3. NSManagedObjectContext's -mergeChangesFromContextDidSaveNotification: is helpful.

But let me repeat, please read the document carefully! It's really worth it!


Currently [May 2015] the Apple Concurrency with Core Data documentation is, at best, very misleading as it doesn't cover any of the enhancements in iOS 5 and hence no longer shows the best ways to use core data concurrently. There are two very important changes in iOS 5 - parent contexts and new concurrency/threading types.

I have not yet found any written documentation that comprehensively covers these new features, but the WWDC 2012 video "Session 214 - Core Data Best Practices" does explain it all very well.

Magical Record uses these new features and may be worth a look.

The real basics are still the same - you can still only use managed objects the thread their managed object context was created on.

You can now use [moc performBlock:] to run code on the right thread.

There's no need to use mergeChangesFromContextDidSaveNotification: anymore; instead create a child context to make the changes, then save the child context. Saving the child context will automatically push the changes up into the parent context, and to save the changes to disk just perform a save on the parent context in it's thread.

For this to work you must create the parent context with a concurrent type, eg:

mainManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];

Then on the background thread:

context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSConfinementConcurrencyType];[context setParentContext:mainManagedObjectContext];<... perform actions on context ...>NSError *error;if (![context save:&error]){    <... handle error ...>}[mainManagedObjectContext performBlock:^{    NSError *e = nil;    if (![mainContext save:&e])    {        <... handle error ...>    }}];


I hope this can help all the peoples that meet problems using core data in a multithread environment.

Take a look at "Top Songs 2" in apple documentation. With this code i took the "red pill" of Matrix, and discovered a new world, without double free error, and without faults. :D

Hope this helps.

Paolo

p.s.Many thanks to Yuji, in the documentation you described above I found that example.