Adjusting Your Code
By default, data migration is not turned on for any application. Fortunately it is very easy to turn on automatic code migration, but the manner in which you turn it on is dependent on the type of application you are designing. When it comes to Core Data, there are two application models that differ drastically in their handling of the Core Data Stack: the document model and the non-document model.
Document Model
In a document model, each document has its own Core Data stack that is constructed when the NSPersistentDocument is initialized. In this case, to enable Core Data automatic migration you simply need to override one method call in your subclass of the NSPersistentDocument:
- (BOOL)configurePersistentStoreCoordinatorForURL:ofType:modelConfiguration:storeOptions:error:
When Core Data attempts to load a persistent store, this method is called. To turn on automatic migration, all that is needed is to add the option in the store options as follows:
- (BOOL)configurePersistentStoreCoordinatorForURL:(NSURL*)url ofType:(NSString*)fileType modelConfiguration:(NSString*)configuration storeOptions:(NSDictionary*)storeOptions error:(NSError**)error { NSMutableDictionary *options = nil; if (storeOptions != nil) { options = [storeOptions mutableCopy]; } else { options = [NSMutableDictionary alloc] init]; } [options setObject:[NSNumber numberWithBool:YES] forKey:NSMigratePersistentStoresAutomaticallyOption]; BOOL result = [super configurePersistentStoreCoordinatorForURL:url ofType:fileType modelConfiguration:configuration storeOptions:options error:error]; [options release], options = nil; return result; }
Once you have set the NSMigratePersistentStoresAutomaticallyOption flag, Core Data will attempt to automatically migrate any persistent store that does not match the store that is flagged as current.
Non-Document Model
Things are a bit different in a non–document-based application. Generally, the loading and handling of the Core Data stack is performed in the application delegate instead of in a document object. Therefore configuring Core Data to do automatic migration is also a bit different.
Normally, a non–document-based application will have a method to load up the persistent store that looks something like the following:
- (NSPersistentStoreCoordinator *) persistentStoreCoordinator { if (persistentStoreCoordinator) return persistentStoreCoordinator; NSFileManager *fileManager = [NSFileManager defaultManager]; NSString *applicationSupportFolder = [AbstractManagedObject applicationSupportFolder]; if ( ![fileManager fileExistsAtPath:applicationSupportFolder isDirectory:NULL] ) { [fileManager createDirectoryAtPath:applicationSupportFolder attributes:nil]; } NSURL *url = [NSURL fileURLWithPath: [applicationSupportFolder stringByAppendingPathComponent: @"MyApplication.xml"]]; persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]]; NSError *error = nil; if (![persistentStoreCoordinator addPersistentStoreWithType:NSXMLStoreType configuration:nil URL:url options:nil error:&error]) { [[NSApplication sharedApplication] presentError:error]; } return persistentStoreCoordinator; }
The only change that is required to turn on automatic store migration is to add the option, similar to the document model above, to the -(id)addPersistentStoreWithType: configuration: URL: options: error: method. You can see the change in the updated method below:
- (NSPersistentStoreCoordinator *) persistentStoreCoordinator { if (persistentStoreCoordinator) return persistentStoreCoordinator; NSFileManager *fileManager = [NSFileManager defaultManager]; NSString *applicationSupportFolder = [AbstractManagedObject applicationSupportFolder]; if ( ![fileManager fileExistsAtPath:applicationSupportFolder isDirectory:NULL] ) { [fileManager createDirectoryAtPath:applicationSupportFolder attributes:nil]; } NSURL *url = [NSURL fileURLWithPath: [applicationSupportFolder stringByAppendingPathComponent: @"MyApplication.xml"]]; persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]]; NSError *error = nil; //Turn on automatic store migration NSMutableDictionary *optionsDictionary = [NSMutableDictionary dictionary]; [optionsDictionary setObject:[NSNumber numberWithBool:YES] forKey:NSMigratePersistentStoresAutomaticallyOption]; if (![persistentStoreCoordinator addPersistentStoreWithType:NSXMLStoreType configuration:nil URL:url options:nil error:&error]) { [[NSApplication sharedApplication] presentError:error]; } return persistentStoreCoordinator; }
With that one change, Core Data will detect and migrate your persistent stores automatically.