Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

deleting core data persistent store instead of migrating (also using RestKit)

I'm making quite a few changes to the object model for our app upgrade release ie. entities added / removed, new attributes and relationships. It seems like the work would really add up for a proper core data migration. Since the data primarily serves as a cache to enhance the offline browsing experience. at this point doesnt really need migration I would think it would be a whole lot simpler if it were just blown away and recreated.

Based on various posts I've come across on this topic the general strategy is to

  • detect that the model has changed (by catching the exception during initialization of the managedObjectContext)
  • delete the persistent store (in our case on iOS the sqlite file)
  • reinitialize an objectModel with the latest schema reinitialize a persistent store with the new model

This is the code that reinitializes the objectModel

- (NSManagedObjectModel *)managedObjectModel {

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

NSString *path = [[NSBundle mainBundle] pathForResource:@"<model name>" ofType:@"momd"];
NSURL *momURL = [NSURL fileURLWithPath:path];
managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:momURL];

return managedObjectModel; 
}

and recreating the objectModel and store with

objectManager = [RKObjectManager objectManagerWithBaseURL:
                     [NSString stringWithFormat:@"http://%@/v3", 
                      [[NSBundle mainBundle] objectForInfoDictionaryKey:@"APIDomain"]]];     
NSManagedObjectModel *objectModel = [self managedObjectModel];
objectManager.objectStore = [RKManagedObjectStore objectStoreWithStoreFilename:storeName usingSeedDatabaseName:nil managedObjectModel:objectModel delegate:nil]; 

However, I get the following error:

Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '+entityForName: could not locate an NSManagedObjectModel for entity name 'UTCity''

I feel like it's pretty close since restarting the app succeeds in creating a new store runs correctly.

-PF

like image 946
PFaunik Avatar asked Mar 06 '12 22:03

PFaunik


2 Answers

I think I've been able to do what you're describing by implementing a method from RKManagedObjectStoreDelegate. The method is called when the persistent store creation fails. I simply delete the persistent store when this method is called. RestKit seems to recover from this just fine. I assume it created the new blank store next time it needs it.

- (void)managedObjectStore:(RKManagedObjectStore *)objectStore didFailToCreatePersistentStoreCoordinatorWithError:(NSError *)error {
    [objectStore deletePersistentStore];
}

RKManagedObjectStore attempts to create the persistent store at initialization, so you'll need to initialize your instance of RKManagedObjectStore via one of the methods that accepts a delegate object. I just passed in my app delegate.

So far, this seems to work. As I continue developing, we'll see if it continues to do so.

like image 132
CharlieMezak Avatar answered Sep 28 '22 11:09

CharlieMezak


Here is a solution to delete the persistent store altogether when migration fails.

    // Core Data Persistent Store
    NSError *error;
    NSString *storePath = [RKApplicationDataDirectory() stringByAppendingPathComponent:@"Data.sqlite"];
    NSPersistentStore __unused *persistentStore = [managedObjectStore addSQLitePersistentStoreAtPath:storePath
                                                                              fromSeedDatabaseAtPath:nil
                                                                                   withConfiguration:nil
                                                                                             options:@{NSInferMappingModelAutomaticallyOption: @YES, NSMigratePersistentStoresAutomaticallyOption: @YES}
                                                                                               error:&error];

    // Reset the persistant store when the data model changes
    if (error) {

        [[NSFileManager defaultManager] removeItemAtPath:storePath
                                                   error:nil];

        NSPersistentStore __unused *persistentStore = [managedObjectStore addSQLitePersistentStoreAtPath:storePath
                                                                                  fromSeedDatabaseAtPath:nil
                                                                                       withConfiguration:nil
                                                                                                 options:nil
                                                                                                   error:nil];
    }
like image 34
mosca1337 Avatar answered Sep 28 '22 12:09

mosca1337