Что мне нужно сделать, чтобы получить Core Data для автоматической миграции моделей?

Я прочитал в документации об автоматической / облегченной миграции для моделей Core Data - но у меня есть проблемы в реальности ее реализации.

Насколько я понимаю, приложение должно заметить, что его модель и модель, которая существует на устройстве, уже не совпадают. Если вы только добавили атрибуты или отношения и подобные простые изменения, то модель должна быть обновлена ​​автоматически.

Любые указатели - мне нужно установить что-то в xCode?

10 ответов

Решение

Теперь я узнал, что это довольно просто - когда вы знаете, где искать.

В моем AppDelegate я настроил NSPersistentStoreCoordinator - и вам нужно добавить некоторые параметры, чтобы он мог обрабатывать автоматическую миграцию:

NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:

[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,

[NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];

NSError *error;
_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: [self managedObjectModel]];

if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:options error:&error]) {
    // Handle error
    NSLog(@"Problem with PersistentStoreCoordinator: %@",error);
}

Затем вам нужно сделать небольшой трюк в xCode:

  1. Выберите файл xcdatamodel
  2. Выберите меню "Дизайн" вверху - затем Модель данных - затем выберите Добавить версию модели
  3. Затем ваш файл xcdatamodel будет перемещен в новый каталог с тем же именем, что и ваш файл xcdatamodel, но с расширением xcdatamodeld - в этом каталоге будет второй файл с 2 в имени. Выберите новый файл и затем Дизайн-> Модель данных-> Установить текущую версию ( в Xcode 4 вы делаете это)
  4. Если вы уже внесли изменения, которые привели к несовместимости проекта, удалите эти изменения из исходного файла xcdatamodel. Если вам еще предстоит внести изменения - просто отредактируйте файл 2.xcdatamodel (тот, который вы только что сделали в текущей версии).
  5. Теперь, когда вы устанавливаете эту версию на устройство, которое имеет старую модель - оно автоматически обновит эту модель до новой модели.

Это кажется великолепным и таким простым, как я хотел - но я думаю, что вы должны быть осторожны во время разработки при изменении модели - в противном случае вам придется создавать новую версию для каждого изменения.

Я думаю, что я сделаю то, что я сохраню все измененные файлы, а затем, как только я буду готов к развертыванию своего обновления, я удалю все промежуточные файлы и просто разверну с самыми старыми и последними моделями.


ОБНОВЛЕНИЕ (15/07/2011):

Спасибо @ rockstarberlin за указание на обновленную документацию на apple:

Xcode 4: Установка текущей версии модели управляемого объекта

Обновление: 19.08.2013, лучшая ссылка:

https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/CoreDataVersioning/Articles/vmModelFormat.html

Это было невероятно полезно. Документация Apple была - как обычно - ужасно неполной. Я рекомендую сделать чистую сборку, так как я столкнулся с ошибкой "Не удается объединить модели с двумя разными объектами xxx", когда я впервые запустил после внесения этих изменений. Чистая сборка исправила это.

Ответ Грушаля идеален... но если у вас все еще есть "Не удается объединить модели с двумя разными сущностями xxx" даже после очистки сборки несколько раз... У вас могут быть проблемы с загрузкой managedObjectModel.. Взгляни на этот... который помог мне исправить это..

основные проблемы миграции данных

Кроме того, если вы наткнулись на этот пост, как я, после получения ошибки "Модель, используемая для открытия магазина, несовместима с моделью, используемой для создания магазина", и вы просто отлаживаете с помощью симулятора и хотите полностью заменить Если установлена ​​старая модель, вы можете просто перезагрузить приложение Simulator, иначе удаление приложения из симулятора, вероятно, также будет работать.

Мне не приходило в голову попробовать это, пока я не прочитал сообщения здесь, и тогда я понял, что установил приложение в симуляторе, а затем изменил модель, что привело к вышеупомянутой ошибке во время выполнения.

Меню в Xcode 4 немного изменилось. Вот описание, как это сделать в Xcode 4:

Xcode 4: Установка текущей версии модели управляемого объекта

У меня была эта проблема в течение многих лет, и я попробовал все эти ответы безрезультатно. Сегодня я наконец понял, что я делаю не так. Очень простая проблема, но я ее упустил. При создании более новой версии модели данных, если вы добавляете столбцы, не забудьте пометить их как НЕОБЯЗАТЕЛЬНЫЕ. Если вы этого не сделаете, простая миграция не будет работать, потому что новые значения столбца не будут заполнены.

Как только я убедился, что мои новые столбцы отмечены как "необязательные", я снова попытался выполнить миграцию, и она заработала.

Я наткнулся на этот пост из-за других проблем, но ошибка была такова: " Конфигурация модели, используемая для открытия магазина, несовместима с той, которая использовалась для создания магазина ".

Здесь была моя проблема и ее решение. В моей модели я использовал конфигурации. У меня были некоторые сущности, хранящиеся в одном файле, а другие во втором файле. (У меня есть некоторые настройки по умолчанию, которые могут периодически нуждаться в загрузке, и было бы невероятно сложно объединить их в единое целое). Во всяком случае, я сделал новую сущность. Программа, казалось, работала нормально, но всякий раз, когда я выходил, я получал вышеуказанную ошибку.

Решением было посмотреть на мои конфигурации, понять, что у меня есть объект, которого в данный момент нет ни в одной из конфигураций, и добавить его в одну. Работает как сон.

Это не решит проблему ОП. Но, возможно, какой-нибудь расстроенный человек, который приземлится здесь через Google, окажется в лодке, в которой я был:)

Чтобы проконтролировать ответ Санттоша, я решил опубликовать фрагмент кода прямо здесь. Вам нужно создать свою управляемую модель с помощью initWithContentsOfURL: вместо mergedModelFromBundles: в противном случае вы получите ошибку:

Не удается объединить модели с двумя разными объектами XXX и XXX

Если ваш файл модели называется "Модель", вот как вы создаете managedObjectModel:

NSString *path = [[NSBundle mainBundle] pathForResource:@"Model" ofType:@"momd"];
NSURL *momURL = [NSURL fileURLWithPath:path];
managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:momURL]; 

Кредит на это сообщение в блоге.

iOS 4.0+

NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"model" withExtension:@"momd"];
managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];

Незначительное редактирование к удивительным инструкциям @Grouchal выше для Xcode версии 5:

Старый: 2. Выберите меню "Дизайн" вверху - затем Модель данных - затем выберите Добавить версию модели.

Версия 5+: 2. Выберите меню "Редактор", затем "Добавить версию модели", введите название версии и "На основе модели" (выберите исходную модель из списка).

Другие вопросы по тегам