Manual CoreData Migration with NSMigrationManager to append Data (preload)
I have a populated sqlite database in my app reousrce-folder. On startup I want to preload coredata-store with the data of this sqlite db. I use the NSMigrationManager in the persistantStoreCoordinator method. This works great at the first time and will append the data to the store. But it will append the data on each startup again, so the data will be duplicated, after the second startup. How can I solve this? In a database I would use primary keys, is there something similar in the data model? Or can I compare the entity-objects?
Thanks four your help, below the method I use:
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
if (persistentStoreCoordinator_ != nil) {
return persistentStoreCoordinator_;
}
NSString *storePath = [[self applicationDocumentsDirectory] stringByAppendingPathComponent:@"Raetselspass.sqlite"];
NSURL *storeUrl = [NSURL fileURLWithPath:storePath];
NSString *defaultStorePath = [[NSBundle mainBundle] pathForResource:@"Raetselspass" ofType:@"sqlite"];
NSURL *defaultStoreUrl = [NSURL fileURLWithPath:defaultStorePath];
/*
Set up the store.
For the sake of illustration, provide a pre-populated default store.
*/
// CANNOT USE THIS BELOW: WILL WORK ONCE, BUT WHEN I WILL UPDATE THE APP WITH
// NEW DATA TO APPEND, THEN THIS WILL NOT WORK
// NSFileManager *fileManager = [NSFileManager defaultManager];
// If the expected store doesn’t exist, copy the default store.
// if (![fileManager fileExistsAtPath:storePath]) {
// if (defaultStorePath) {
// [fileManager copyItemAtPath:defaultStorePath toPath:storePath error:NULL];
// }
// }
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption, [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];
persistentStoreCoordinator_ = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: [self managedObjectModel]];
NSError *error;
if (![persistentStoreCoordinator_ addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:options error:&error]) {
// Update to handle the error appropriately.
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort(); // Fail
}
//migration
rror:&error];
NSError *err = nil;
NSMigrationManager *migrator = [[NSMigrationManager alloc] initWithSourceModel:[self managedObjectModel] destinationModel:[self managedObjectModel]];
NSMappingModel *mappingModel = [NSMappingModel inferredMappingModelForSourceModel:[self managedObjectModel] destinationModel:[self managedObjectModel] error:&err];
NSError *err2;
if (![migrator migrate开发者_StackOverflow社区StoreFromURL:defaultStoreUrl
type:NSSQLiteStoreType
options:nil
withMappingModel:mappingModel
toDestinationURL:storeUrl
destinationType:NSSQLiteStoreType
destinationOptions:nil
error:&err2])
{
//handle the error
}
NSLog(@"import finished");
[migrator release];
return persistentStoreCoordinator_;
}
The code as provided will merge the default file if it is present in the documents folder. If you delete the file after you merge it, then it shouldn't load every time. You could set a user default flag to record if it had been previously merged.
A better solution would be to create a Core Data persistent store with the default data and include that in the app bundle. Upon first launch, copy that file to the documents folder and just assign it to the persistent store. That method would be faster and you wouldn't have to worry about the merge failing.
精彩评论