Реализация "Автоматическая легкая миграция" для основных данных (iPhone)

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

В руководстве от Apple это единственная информация по этому вопросу, которую я мог найти:

Автоматическая легкая миграция

Чтобы запросить автоматический легкий вес миграции, вы устанавливаете соответствующие флаги в словаре опций, которые вы передаете addPersistentStoreWithType: Конфигурация: URL: опции: ошибка:. Вам нужно установить соответствующие значения как для NSMigratePersistentStoresAutomaticallyOption и NSInferMappingModelAutomaticallyOption клавиши YES:

NSError *error;
NSURL *storeURL = <#The URL of a persistent store#>;
NSPersistentStoreCoordinator *psc = <#The coordinator#>;
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
    [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
    [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];

if (![psc addPersistentStoreWithType:<#Store type#>
    configuration:<#Configuration or nil#> URL:storeURL
    options:options error:&error]) {
    // Handle the error.
}

My NSPersistentStoreCoordinator инициализируется следующим образом:

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {

    if (persistentStoreCoordinator != nil) {
        return persistentStoreCoordinator;
    }

    NSURL *storeUrl = [NSURL fileURLWithPath: [[self applicationDocumentsDirectory] stringByAppendingPathComponent: @"FC.sqlite"]];

    NSError *error = nil;
    persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
    if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:nil error:&error]) {

        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    }    

    return persistentStoreCoordinator;
}

У меня возникли проблемы с тем, как и как я должен добавить код Apple для работы автоматической облегченной миграции?

Ответ 1

Это то, что я сделал, чтобы сделать автоматическую легкую миграцию (Источник: http://brainwashinc.wordpress.com/2010/01/18/iphone-coredata-automatic-light-migration/)

1. Установите параметры Persistent Store для автоматической миграции в делегате приложения.

Измените ваше постоянное созданиеStoreCoordinator на это (замените YOURDB):

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {

  if (persistentStoreCoordinator != nil) {
    return persistentStoreCoordinator;
  }

  NSURL *storeUrl = [NSURL fileURLWithPath: [[self applicationDocumentsDirectory] stringByAppendingPathComponent: @"YOURDB.sqlite"]];

  // handle db upgrade
  NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
  [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
  [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];

  NSError *error = nil;
  persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: [self managedObjectModel]];
  if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:options error:&error]) {
    // Handle error
  }

  return persistentStoreCoordinator;
}

2. Верните свою модель данных и отредактируйте новый файл.

Выберите файл xcdatamodel Дизайн → Модель данных → Добавить версию модели (разверните элемент xcdatamodeld) Выберите "2" (или более поздний) файл, "Дизайн" → "Модель данных" → "Установить текущую версию" (отредактируйте эту версию).

3. Укажите ресурс momd в делегате приложения.

Измените реализацию managedObjectModel на это (замените YOURDB)

- (NSManagedObjectModel *)managedObjectModel {

  if (managedObjectModel != nil) {
    return managedObjectModel;
  }

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

  return managedObjectModel;
}

Ответ 2

Сначала это решение не сработало для меня. Возвращаемая команда managedObjectModel была 0x0. Я думаю, это связано с тем, что я переименовал имена файлов в разных файлах модели. Если вы следуете приведенным выше инструкциям в письме, все это работает.

Однако, если вы измените имена файлов моделей, вы можете вручную выбрать "текущий" файл модели: Допустим, ваш оригинальный файл модели был MYMODEL.xcdatamodel после того, как шаг добавления модели выше, он превращается в каталог MY.xcdatamodeld и под ним у вас есть MYMODEL.xcdatamodel и MYMODEL 2.xcdatamodel переименуйте новый файл модели во все, что вы хотите, например, скажем, вы удалили пространство в MYMODEL2.xcdatamodel и отредактировали его содержимое. Теперь в приведенном выше коде do

NSString *path = [mainBundle pathForResource:@"MYMODEL2" ofType:@"mom" inDirectory:@"MYMODEL.momd"];

Ответ 3

Я думаю, что это добавляет последний ответ.

Я обнаружил, что использование ресурса пакета и имена .sqlite действительно запутывают сначала. Изменяется ли имя ресурса узла с изменением версии? Изменено ли имя .sqlite? Теперь у меня появилась моя миграция, и узнал, что имя модели связки относится к имени каталога/папки в XCode, содержащем все модели, а не имени версий модели в этом каталоге.

Когда вы даете имя моделиResource для:

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

Это имя моделиResource является каталогом/папкой для моделей в Xcode.

Когда вы выполните:

    NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:storeFileName];
    NSError *error = nil;

    if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error]) {
        // handle error
    }

StoreFileName - это имя вашего файла .sqlite в папке Documents/directory (это не в комплекте).

Кроме того, при переходе с одной версии модели на другую версию модели по умолчанию имя файла .sqlite остается неизменным.

Ответ 4

Оскар, в ответ на вашу проблему, я нашел то же самое сначала. Я бы предложил удалить и повторно добавить новый файл .xcdatamodeld в ваш проект, а затем перестроить. Надеюсь, это поможет!

Ответ 5

Решение Swift 3

1. Установите параметры Persistent Store для автоматической миграции в делегате приложения.

Измените ваше создание persistentStoreCoordinator на это (замените SingleViewCoreData.sqlite):

lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator = {


let coordinator: NSPersistentStoreCoordinator = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)
let url = self.applicationDocumentsDirectory.appendingPathComponent("SingleViewCoreData.sqlite")

let options = [
  NSMigratePersistentStoresAutomaticallyOption : Int(true),
  NSInferMappingModelAutomaticallyOption : Int(true)
]

do {

  try coordinator.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: url, options: options)

} catch {

  print(error)
}

return coordinator

}()

2. Верните свою модель данных и отредактируйте новый файл.

Выберите файл xcdatamodel Редактор файлов > Добавить версию модели - добавьте имя для новой модели