Question

How do you create a NSManagedObjectContext that has a non nil parentContext that runs on a different queue/thread?

UIManagedDocument's managedObjectContext does have this, but I don't know how to replicate it without using UIManagedDocument.

This is the code I'm using, which results in a managedObjectContext whose parentContext property is nil.

-(NSManagedObjectContext *)context{

    if (_context == nil){
        _context = [[NSManagedObjectContext alloc] init];
        _context.persistentStoreCoordinator = self.storeCoordinator;
    }
    return _context;
}

-(NSPersistentStoreCoordinator *) storeCoordinator{
    if (_storeCoordinator == nil) {
        _storeCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:self.model];

        NSError *err = nil;
        if (![_storeCoordinator addPersistentStoreWithType:NSSQLiteStoreType
                                             configuration:nil
                                                       URL:self.dbURL
                                                   options:nil
                                                     error:&err ]) {

            NSLog(@"Error while adding a Store: %@", err);
            return nil;

        }
    }
    return _storeCoordinator;
}

-(NSManagedObjectModel *) model{

    if (_model == nil) {
        _model = [[NSManagedObjectModel alloc] initWithContentsOfURL:self.modelURL];
    }
    return _model;
}
Was it helpful?

Solution

You create the child context by just allocating it and setting its parent:

NSManagedObjectContext *childContext = [[NSManagedObjectContext alloc] init];
[childContext setParentContext:[self managedObjectContext]];

The persistent store coordinator is inherited from the parent context, so this is all you need to create the child. But the parent context must use one of the queue-based concurrency types. That means that your code above creating the context would have to change to something like:

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

There's also NSPrivateQueueConcurrencyType. Which is better depends on your app's design.

The runs on a different queue/thread thing is a different matter though. This is never automatic. Your code runs on whatever queue or thread you call it from. Core Data's direct support is limited to using one of the queue-based concurrency types-- but then you need to make sure to use performBlock: or performBlockAndWait: to ensure that the context's operations actually happen on the right queue.

OTHER TIPS

After creating the NSManagedObjectContext you have to assign the parent context if you need it to be a child context.

[newContext setParentContext:mainThreadManagedObjectContext];

In this case you do not even have to assign the persistent store. From the docs:

Rather than specifying a persistent store coordinator for a managed object context, you can now specify a parent managed object context using setParentContext:. This means that fetch and save operations are mediated by the parent context instead of a coordinator.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top