1
votes

I have an iphone app that uses Core Data to do storage. I have successfully deployed it, and now I'm working on the second version. I've run into a problem with the data model that will require a few very simple data transformations at the time that the persistent store gets upgraded, so I can't just use the default inferred mapping model.

My object model is stored in an .xcdatamodeld bundle, with versions 1.0 and 1.1 next to each other. Version 1.1 is set as the active version. Everything works fine when I use the default migration behavior and set NSInferMappingModelAutomaticallyOption to YES. My sqlite storage gets upgraded from the 1.0 version of the model, and everything is good except for, of course, the few transformations I need done.

As an additional experimental step, I added a new Mapping Model to the core data model bundle, and have made no changes to what xcode generated. When I run my app (with an older version of the data store), I get the following

* Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Object's persistent store is not reachable from this NSManagedObjectContext's coordinator'

What am I doing wrong? Here's my code for to get the managed object model and the persistent store coordinator.

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {

    if (_persistentStoreCoordinator != nil) {
        return _persistentStoreCoordinator;
    }

    _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];

    NSURL *storeUrl = [NSURL fileURLWithPath: [[self applicationDocumentsDirectory] stringByAppendingPathComponent: @"gti_store.sqlite"]];

    NSError *error;
    NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
                             [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
                             [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];

    if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType 
                                                   configuration:nil 
                                                             URL:storeUrl 
                                                         options:options 
                                                           error:&error]) {
        NSLog(@"Eror creating persistent store coodinator - %@", [error localizedDescription]);
    }    

    return _persistentStoreCoordinator;
}


- (NSManagedObjectModel *)managedObjectModel {

    if(_managedObjectModel == nil) {

        _managedObjectModel = [[NSManagedObjectModel mergedModelFromBundles:nil] retain];    
        NSDictionary *entities = [_managedObjectModel entitiesByName];

        //add a sort descriptor to the 'Foo' fetched property so that it can have an ordering - you can't add these from the graphical core data modeler
        NSEntityDescription *entity = [entities objectForKey:@"Foo"];   
        NSFetchedPropertyDescription *fetchedProp = [[entity propertiesByName] objectForKey:@"orderedBar"];
        NSSortDescriptor* sortDescriptor =  [[[NSSortDescriptor alloc] initWithKey:@"index" ascending:YES] autorelease];
        NSArray* sortDescriptors = [NSArray arrayWithObjects:sortDescriptor, nil];
        [[fetchedProp fetchRequest] setSortDescriptors:sortDescriptors];
    }
    return _managedObjectModel;
}
4

4 Answers

5
votes

I haven't thought this out very carefully, it's just an observation as I was having the same problem, and I too have found very few references to this error on the web.

In my case the problem was that I had setup one of my application's objects to observe

NSManagedObjectContextObjectsDidChangeNotification like so

        [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(observeContextSave:)
                                                 name:NSManagedObjectContextDidSaveNotification
                                               object:nil];


- (void) observeContextSave:(NSNotification*) notification {
[[self managedObjectContext] mergeChangesFromContextDidSaveNotification:notification];}

Once I moved this code so that is was executed after the migration, the error went away.

Anyway. I'm sure your circumstances are different. But it may help to think about what observations you have setup on notifications from your managedObjectContext.

Update: Having thought about this a bit more, I guess it happens because multiple persistent stores are created during migration, which means that NSManagedObjectContextDidSaveNotification will be sent from a context with a different persistent store to the context that is sent mergeChangesFromContextDidSaveNotification.

4
votes

First, turn off the automatic migration if you are having a mapping model, fair chance they are colliding. Once you have done that, confirm that the error is gone.

0
votes

I had similar issue when persistent store initialization was performed from secondary thread. After I forced initialization in primary thread the problem has gone. Weird.

0
votes

Seems you already got it fixed, but worth to mention. I had this error too, the reason was I had multiple MOCs being notified of mergeChangesFromContextDidSaveNotification while they had different persistent stores (or different schemas). They didn't know how to handle changes that didn't belong to their stores.