Replacing a Core Data Store While the Engine's Running

It's actually quite easy to replace your Core Data backing store even while your application is in use. For example, you may want to replace all the data on the device when a user restores from a backup. In this scenario you could perform the import operation using a separate store, quickly replacing the current store when the data has been restored.

So let's say we've finished building our new store. We've got the file URL of our new store and we're ready to replace our default store. The first thing we need to do is reset our app's managed object context so that it won't contain stale data when the store is replaced.

[managedObjectContext reset];

The next thing we need to do is remove the current store(s) from our persistent store coordinator. There could be more than one so we enumerate them and remove them one at a time.

NSError *error;
for (NSPersistentStore *store in persistentStoreCoordinator.persistentStores) {
    BOOL removed = [persistentStoreCoordinator removePersistentStore:store error:&error];

    if (!removed) {
        NSLog(@"Unable to remove persistent store: %@", error);
    }
}

Now we replace our default store file with the one we have saved at a temporary URL.

NSError *error;
BOOL moved = [[NSFileManager defaultManager] replaceItemAtURL:defaultStoreURL
                                                withItemAtURL:tempStoreURL
                                               backupItemName:nil
                                                      options:0
                                             resultingItemURL:nil
                                                        error:&error];

if (!moved) {
    NSLog(@"Unable to move temporary store: %@", error);
}

With the new file successfully copied over the old one we can now add our new persistent store to our existing coordinator.

NSError *error;
NSDictionary *options = @{
        NSMigratePersistentStoresAutomaticallyOption : @YES,
        NSInferMappingModelAutomaticallyOption : @YES
};
NSPersistentStore *persistentStore = [persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType
                                                                              configuration:nil
                                                                                        URL:defaultStoreURL
                                                                                    options:options
                                                                                      error:&error];
if (!persistentStore) {
    NSLog(@"Unable to add new store: %@", error);
}

Because the persistent store coordinator sits between any managed object context(s) and the store itself we don't have to rebuild our Core Data stack. All we need to do now is reload any data that our views need.

"Replacing a Core Data Store While the Engine's Running" was originally published on 09 Mar 2014.