Реализация "Автоматической облегченной миграции" для базовых данных (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> Добавить версию модели - добавьте имя для вашей новой модели