PFaunik
PFaunik

Reputation: 161

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

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

Upvotes: 7

Views: 1441

Answers (2)

mosca1337
mosca1337

Reputation: 2429

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];
    }

Upvotes: 3

CharlieMezak
CharlieMezak

Reputation: 5999

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.

Upvotes: 6

Related Questions