Everything I've read about using Core Data on multiple threads talks about using multiple NSManagedObjectContext
instances sharing a single NSPersistentStoreCoordinator
. This is understood and I've made it work in an app that uses Core Data on the main thread in support of the UI and has a background fetch operation that can take a while to run.
The problem is that access to the underlying SQLite persistent store is serialized by the NSPersistentStoreCoordinator
, so there are still occasions where the UI is blocked by the background fetch operation.
The background fetch operation will never update the data, only read from it. Can I set up an entirely parallel Core Data stack (NSManagedObjectContext
, NSManagedPersistentStoreCoordinator
, and NSManagedObjectModel
) on the background thread connected to the same underlying SQLite persistent store? It seems like this would give complete concurrency between the UI thread and the background fetch operation.
Multiple persistent stores for NSPersistentStoreCoordinator The first would be the big one in the bundle, and the second could be a small one in the documents folder, storing special "favorite" entities with relationships to the big store.
The persistent store coordinator's role is to manage these stores and present to its managed object contexts the facade of a single unified store. When you fetch records, Core Data retrieves results from all of them, unless you specify which store you're interested in.
A persistent store is a repository in which managed objects may be stored. You can think of a persistent store as a database data file where individual records each hold the last-saved values of a managed object. Core Data offers three native file types for a persistent store: binary, XML, and SQLite.
Core Data can use SQLite as its persistent store, but the framework itself is not a database. Core Data is not a database. Core Data is a framework for managing an object graph. An object graph is nothing more than a collection of interconnected objects.
My own tentative answer to this is now yes.
I initialize my background operation by passing it the NSPersistentStore
instance. On the background thread, the properties of this store, including the URL, are used to create a whole new Core Data stack like this:
// create managed object model
NSURL *modelUrl = [[NSBundle bundleForClass:[self class]] URLForResource:@"..." withExtension:@"..."];
NSManagedObjectModel *managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelUrl];
// create persistent store coordinator
NSPersistentStoreCoordinator *persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:managedObjectModel];
NSError *error = nil;
[persistentStoreCoordinator addPersistentStoreWithType:[store type]
configuration:[store configurationName]
URL:[store URL]
options:[store options]
error:&error];
// create managed object context
NSManagedObjectContext *context = [[NSManagedObjectContext alloc] init];
[context setPersistentStoreCoordinator:persistentStoreCoordinator];
[persistentStoreCoordinator release];
[managedObjectModel release];
I then perform the background fetch using this newly created NSManagedObjectContext
instance.
Everything seems to work just fine. I'm not yet accepting my own answer, though, as I would love to have someone provide supporting or contradicting evidence to my findings.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With