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

96

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

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

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

Grouchal
источник

Ответы:

138

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

В моем 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 в имени. Выберите новый файл, а затем Design-> Data Model-> Set Current Version ( в 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

Grouchal
источник
Я бы посоветовал прочитать Руководство по миграции основных данных и управлению версиями, доступное в программе просмотра документов Xcode и на сайте developer.apple.com.
Hunter
1
Я не нашел там простого ответа - потребовалось время, чтобы узнать, как это сделать.
Grouchal
NSInferMappingModelAutomaticallyOption работает хорошо, но только для простых сопоставлений, таких как изменение имени атрибута. Для чего-то более сложного (отношения, удаление или добавление сущностей) вам нужно будет добавить модель сопоставления. Если Xcode жалуется, что NSInferMappingModelAutomaticallyOption не объявлен, добавьте #import <CoreData / CoreData.h> в файл заголовка делегата вашего приложения.
Elise van Looij,
Я добавил несколько сущностей в свою модель и получил печально известную ошибку «Модель, использованная для открытия магазина, несовместима с той, которая использовалась для создания магазина». Ваше решение исправило это! Большое спасибо!
Karsten Silz
1
См. Ответ Санттоша ниже, если после выполнения этих инструкций вы получаете сообщение об ошибке «не удается объединить модели с двумя разными объектами с именем».
benvolioT
14

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

Скотт Минс
источник
В чистой сборке мои проблемы тоже были исправлены.
jrainbow
6

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

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

Santthosh
источник
3

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

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

Дрейлн
источник
1

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

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

Если ваш файл модели называется «Модель», вы можете создать управляемый объектModel следующим образом:

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

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

Самвермет
источник
1

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

Как только я убедился, что в моих новых столбцах установлен флажок «optional», я снова попробовал миграцию, и это сработало.

Мозг2000
источник
1

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

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

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

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

Кэппи
источник
0

iOS 4.0+

NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"model" withExtension:@"momd"];
managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
Стиан Хойланд
источник
0

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

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

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

PGSeattle
источник