iosobjective-ccore-datarestkit-0.20nspersistentstore

Automatically drop and re-create Persistent Data Store with Core Data + RestKit 0.2.x


While in the early stages of developing my app that uses Core Data and RestKit I often modify the data model quite heavily and find little or no use to even think about migrations.

I'd like the logic to be:

IF (there is a foolproof, automatic migration path) THEN
   TRY { foolproof path; }
   CATCH { brute path; }
ELSE
   brute path;

brute path:

IF (SqlLiteDatabase exists) THEN
   DELETE IT;

CREATE SqlLiteDatabase;

What I have now, I honestly do not understand...

RKObjectManager *objectManager = [RKObjectManager managerWithBaseURL:[NSURL URLWithString:[[RestKitClientConfigurator webServiceConfiguration] baseURL]]];

NSManagedObjectModel *managedObjectModel = [NSManagedObjectModel mergedModelFromBundles:nil];
RKManagedObjectStore *managedObjectStore = [[RKManagedObjectStore alloc] initWithManagedObjectModel:managedObjectModel];
objectManager.managedObjectStore = managedObjectStore;

[managedObjectStore createPersistentStoreCoordinator];
NSString *storePath = [RKApplicationDataDirectory() stringByAppendingPathComponent:@"CTISDB.sqlite"];
NSString *seedPath = [[NSBundle mainBundle] pathForResource:@"RKSeedDatabase" ofType:@"sqlite"];

NSDictionary *optionsDictionary =
[NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES]
                            forKey:NSMigratePersistentStoresAutomaticallyOption];

NSError *error;
NSPersistentStore *persistentStore = [managedObjectStore addSQLitePersistentStoreAtPath:storePath fromSeedDatabaseAtPath:seedPath withConfiguration:nil options:nil error:&error];
NSAssert(persistentStore, @"Failed to add persistent store with error: %@", error);

But basically, what I am really wondering is - isn't this by now a common enough problem (having to constantly reset virtual device) that there is a way to tell Core Data just to blow it up?

And if not, what am I missing about the complexity of this operation that prevents the above algorithm from being implemented?


Solution

  • Don't know if this would affect RestKit, but here is my usual development setup when developing an evolving Core Data application:

    1. Set a flag to wipe the store on each run.
    2. In the persistentStoreCoordinator method, delete the store file just before calling addPersistentStore... if the flag is set.
    3. Add a DataPopulator class that conveniently populates the database with imported or random generated dummy data, best also based on a flag.

    Once you are ready or want to test data you have created in the app before, just change the flags. It's very convenient.

    While this would correspond to your "brute force" method, I have found it to be the simplest and most efficient for rapid development cycles. Also, I cannot see any disadvantage compared to a "less brutish" migration process unless your in-app generated data is really critical for development, which tends to be rare.

    BTW, the data populator can come in very handy later if you need to generate seed data, or if you want to stress-test the system with large amounts of records.

    Adding some code for deleting the store:

    - (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
       if (_persistentStoreCoordinator != nil) {
          return _persistentStoreCoordinator;
       }
       _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] 
           initWithManagedObjectModel:[self managedObjectModel]];
       NSURL *storeURL = // get the store URL
       if (kWipeDB) {
            [[NSFileManager defaultManager] removeItemAtURL:storeURL error:nil];
       }
       // add persistent store
       return _persistentStoreCoordinator;
    }
    

    You would find this method in the AppDelegate if you used XCode's standard Core Data template.