开发者

Manual CoreData Migration with NSMigrationManager to append Data (preload)

开发者 https://www.devze.com 2023-01-28 05:21 出处:网络
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 persistantStoreCoordinato

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.

0

精彩评论

暂无评论...
验证码 换一张
取 消