Sometimes you need to change your NSPersistentStore file from one location to another. Or you want to add other options that the old store didn’t have (for example, add iCloud or turn an XML store into an SQLite store). In those cases you can migrate the current store.
Typically this is done by leaving the existing store as is, creating a new store with new properties. Then we’ll tell the NSPersistentStoreCoordinator about our plan, and he’ll swap out the store for us.
Here’s an example: I’ve created a Master/Detail Test App with Core Data and added a few records. All looks good. My persistent store was created by default like this – as provided by the template in AppDelegate.m:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator { if (_persistentStoreCoordinator != nil) { return _persistentStoreCoordinator; } NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"OldStore.sqlite"]; NSError *error = nil; _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]]; if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) { NSLog(@"Unresolved error %@, %@", error, [error userInfo]); abort(); } return _persistentStoreCoordinator; } |
Now I’d like to change the location of the store to a new URL. While I’m at it I could add a new options dictionary – but I won’t show that here, because I’m pretty sure you know how that works 😉
Here’s a method I’m using for the migration:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
- (void)migrateStore { // grab the current store NSPersistentStore *currentStore = self.persistentStoreCoordinator.persistentStores.lastObject; // create a new URL NSURL *newStoreURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"NewStore.sqlite"]; // setup new options dictionary if necessary // migrate current store to new URL [self.persistentStoreCoordinator migratePersistentStore:currentStore toURL:newStoreURL options:nil withType:NSSQLiteStoreType error:nil]; } |
You can check if the migration has worked by writing out the URL before and after the migration. At this point the old store is no longer in use. If you’d like to go back it it at any time, simply perform another migration.
Demo Project
I’ve added a demo project on GitHub which demonstrates this: