Ответ 1
Вот основной процесс:
-
Создайте копию с версией модели данных. (Выберите модель, затем Редактор- > Добавить версию модели)
-
Внесите свои изменения в новую копию модели данных
-
Отметьте копию новой модели данных в качестве текущей версии. (Щелкните элемент верхнего уровня xcdatamodel, затем в инспекторе файлов установите "Текущая" запись в разделе "Модель версий данных" в новую модель данных, созданную на шаге 1.
-
Обновите объекты модели, чтобы добавить объект RecipeIngredient. Также замените отношения ингредиентов и рецептов на объектах Рецепт и Ингредиент с новыми отношениями, которые вы создали на шаге 2, к объекту RecipeIngredient Entity. (Оба объекта добавили это отношение. Я назвал мои рецептыИнградиенты). Очевидно, везде, где вы создаете отношение от ингредиента к рецепту в старом коде, вам теперь нужно создать объект RecipeIngredient.. но это выходит за рамки этого ответа.
-
Добавить новое сопоставление между моделями (File- > New File...- > (раздел Core Data) → Mapping Model. Это автоматически сгенерирует несколько сопоставлений для вас. RecipeToRecipe, IngredientToIngredient и RecipeIngredient.
-
Удалить отображение рецептуры. Также удалите сопоставления отношений рецептаIngredient, которые он дает вам для RecipeToRecipe и IngredientToRecipe (или как вы их называли на шаге 2).
-
Перетащите карту RecipeToRecipe, чтобы быть последним в списке правил сопоставления. (Это важно, чтобы мы были уверены, что Ингридиенты перенесены до Рецептов, чтобы мы могли связать их, когда мы переносим рецепты.) Миграция пойдет в порядке списка правил миграции,
-
Задайте настраиваемую политику для отображения RecipeToRecipe "DDCDRecipeMigrationPolicy" (это переопределит автоматическую миграцию объектов Recipes и даст нам крючок, где мы можем выполнить логику отображения.
-
Создайте DDCDRecipeMigrationPolicy, выполнив подкласс NSEntityMigrationPolicy for Recipes, чтобы переопределить createDestinationInstancesForSourceInstance (см. код ниже). Это будет вызываться один раз для каждого рецепта, который позволит нам создать объект "Рецепт", а также связанные объекты RecipeIngredient, которые свяжут его с Ingredient. Мы просто позволим Ингридиенту автоматически мигрировать по правилу сопоставления, которое Xcode автоматически создает для нас на шаге 5.
-
Если вы создаете хранилище постоянных объектов (возможно, AppDelegate), убедитесь, что пользовательский словарь автоматически переносит модель данных:
if (![__persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType
configuration:nil
URL:storeURL
options:[NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption, nil]
error:&error])
{
}
Подкласс NSEntityMigrationPolicy для рецептов
#import <CoreData/CoreData.h>
@interface DDCDRecipeMigrationPolicy : NSEntityMigrationPolicy
@end
* Заменить createDestinationInstancesForSourceInstance в DDCDRecipeMigrationPolicy.m *
- (BOOL)createDestinationInstancesForSourceInstance:(NSManagedObject *)sInstance entityMapping:(NSEntityMapping *)mapping manager:(NSMigrationManager *)manager error:(NSError **)error
{
NSLog(@"createDestinationInstancesForSourceInstance : %@", sInstance.entity.name);
//We have to create the recipe since we overrode this method.
//It called once for each Recipe.
NSManagedObject *newRecipe = [NSEntityDescription insertNewObjectForEntityForName:@"Recipe" inManagedObjectContext:[manager destinationContext]];
[newRecipe setValue:[sInstance valueForKey:@"name"] forKey:@"name"];
[newRecipe setValue:[sInstance valueForKey:@"overview"] forKey:@"overview"];
[newRecipe setValue:[sInstance valueForKey:@"instructions"] forKey:@"instructions"];
for (NSManagedObject *oldIngredient in (NSSet *) [sInstance valueForKey:@"ingredients"])
{
NSFetchRequest *fetchByIngredientName = [NSFetchRequest fetchRequestWithEntityName:@"Ingredient"];
fetchByIngredientName.predicate = [NSPredicate predicateWithFormat:@"name = %@",[oldIngredient valueForKey:@"name"]];
//Find the Ingredient in the new Datamodel. NOTE!!! This only works if this is the second entity migrated.
NSArray *newIngredientArray = [[manager destinationContext] executeFetchRequest:fetchByIngredientName error:error];
if (newIngredientArray.count == 1)
{
//Create an intersection record.
NSManagedObject *newIngredient = [newIngredientArray objectAtIndex:0];
NSManagedObject *newRecipeIngredient = [NSEntityDescription insertNewObjectForEntityForName:@"RecipeIngredient" inManagedObjectContext:[manager destinationContext]];
[newRecipeIngredient setValue:newIngredient forKey:@"ingredient"];
[newRecipeIngredient setValue:newRecipe forKey:@"recipe"];
NSLog(@"Adding migrated Ingredient : %@ to New Recipe %@", [newIngredient valueForKey:@"name"], [newRecipe valueForKey:@"name"]);
}
}
return YES;
}
Я бы разместил изображение установки в Xcode и образце проекта Xcode, но у меня нет точек репутации при переполнении стека... поэтому он не позволит мне. Я отправлю это в свой блог. bingosabi.wordpress.com/.
Также обратите внимание, что материал для сопоставления модели данных Xcode Core Data немного взломан и иногда нуждается в "чистом", хорошем Xcode-повторе, симуляторе или любом из вышеперечисленных, чтобы он работал.