0
votes

I have some trouble with my migration. Before the migration, I had 2 tables in my model :

  • Food : name (String), category (String), etc...
  • CartFood : name (String), category (String), etc...

I need to create a new entity "Category" and transform the category attributes of both tables to relationships one-to-many. I also want to add attributes to the Food entity and create other entities.

The steps I had follow are the following :

1- Add a model version and create the new Category entity, delete the category attributes, create the relationships, add the new attributes, etc...

2- Create my custom entity migration policy classes (which are subclasses of NSEntityMigrationPolicy) with the same code

- (BOOL)createDestinationInstancesForSourceInstance:(NSManagedObject *)sInstance
                                  entityMapping:(NSEntityMapping *)mapping
                                        manager:(NSMigrationManager *)manager
                                          error:(NSError **)error {    

    NSLog(@"createDestinationInstancesForSourceInstance");

    // Create a new object for the model context
    NSManagedObject *newObject = [NSEntityDescription insertNewObjectForEntityForName:[mapping destinationEntityName] inManagedObjectContext:[manager destinationContext]];

    // Ancienne catégorie
    NSString* oldCategory = [sInstance valueForKey:@"categorie"];
    NSLog(@"oldCategory : %@", oldCategory);

    // Nouvelle catégorie
    [newObject setValue:nil forKey:@"categorie"]; // Nothing for the moment

    // do the coupling of old and new
    [manager associateSourceInstance:sInstance withDestinationInstance:newObject forEntityMapping:mapping];

    return YES;
}

3- Create a mapping model

4- Disable lightweight migration

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
    // Stop that right now if necessary
    if (persistentStoreCoordinator != nil) {
        return persistentStoreCoordinator;
    }

    // Store URL
    NSURL *storeUrl = [NSURL fileURLWithPath: [[self applicationDocumentsDirectory] stringByAppendingPathComponent: @"LeSecretDuPoids.sqlite"]];

    // Get store
    NSError *error = nil;
    NSDictionary *options = @{ NSMigratePersistentStoresAutomaticallyOption : @YES, NSInferMappingModelAutomaticallyOption : @NO };
    persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
    if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:options error:&error]) {
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    }

    return persistentStoreCoordinator;
}

But, when I launch the new app, I got the following error and no logs are displayed to the console :

CoreData: error: -addPersistentStoreWithType:SQLite configuration:(null)

Do I miss something ?

Regards, Sébastien.

1

1 Answers

0
votes

Rather than troubleshooting a custom migration here, which might be difficult, may I suggest you to simply ignore the two string attributes (or re-use them for something else) and use lightweight migration instead?

After the store has been added, you can copy the old string values over into relationships and zero them out in just a few lines of code. E.g.

// create all necessary category objects
// fetch them and all food objects
for (Food *food in allFoodObjects) {
   Category *category = [allCategories filteredArrayUsingPredicate:
    [NSPredicate predicateWithFormat:@"title = %@", food.oldCategory]].firstObject;
   if (category) {
     food.category = category;
   }
}
// repeat with cartfood