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

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

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

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

Чтобы запросить автоматическую облегченную миграцию, вы устанавливаете соответствующие флаги в словаре параметров, который вы передаете в addPersistentStoreWithType:configuration:URL:options:error:. Необходимо установить значения, соответствующие ключам NSMigratePersistentStoresAutomaticsOption и NSInferMappingModelAutomaticsOption, в значение 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.
}

мой 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, чтобы заработала Автоматическая облегченная миграция?

5 ответов

Решение

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

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

Измените свое создание persistentStoreCoordinator на это (замените 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;
}

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

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

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

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

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

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

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

Это имя modelResource является каталогом / папкой для моделей в 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 (его нет в комплекте).

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

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

Swift 3 Solution

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

Измените ваше создание 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> Добавить версию модели - добавьте имя для вашей новой модели

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