Я пытаюсь выполнить облегченную миграцию хранилища SQLite в Core Data. Работа над Lion 10.7.3 с Xcode 4.3.1.
В моем подклассе NSPersistentDocument (AccountDocument) я переопределил метод, используемый для настройки координатора постоянного хранилища, чтобы он получил правильные параметры для миграции:
- (BOOL)configurePersistentStoreCoordinatorForURL:(NSURL *)url ofType:(NSString *)fileType modelConfiguration:(NSString *)configuration storeOptions:(NSDictionary *)storeOptions error:(NSError **)error
{
NSMutableDictionary *newStoreOptions;
if (storeOptions == nil) {
newStoreOptions = [NSMutableDictionary dictionary];
}
else {
newStoreOptions = [storeOptions mutableCopy];
}
[newStoreOptions setObject:[NSNumber numberWithBool:YES] forKey:NSMigratePersistentStoresAutomaticallyOption];
[newStoreOptions setObject:[NSNumber numberWithBool:YES] forKey:NSInferMappingModelAutomaticallyOption];
BOOL result = [super configurePersistentStoreCoordinatorForURL:url ofType:fileType modelConfiguration:configuration storeOptions:newStoreOptions error:error];
return result;
}
(Спасибо Малкольму Кроуфорду за этот совет: http://homepage.mac.com/mmalc/CocoaExamples/controllers.html)
Когда я запускаю приложение, оно не работает в реализации -managedObjectModel
в NSPersistentDocument:
* thread #1: tid = 0x2703, 0x00007fff931d9350 libobjc.A.dylib`objc_msgSend_vtable13 + 16, stop reason = EXC_BAD_ACCESS (code=13, address=0x0)
frame #0: 0x00007fff931d9350 libobjc.A.dylib`objc_msgSend_vtable13 + 16
frame #1: 0x00007fff8935e975 CoreData`-[NSKnownKeysDictionary1 _setValues:retain:] + 197
frame #2: 0x00007fff8935f288 CoreData`_newReadModelFromBytes + 648
frame #3: 0x00007fff8935b93e CoreData`+[NSManagedObjectModel(_NSManagedObjectModelPrivateMethods) _newModelFromOptimizedEncoding:error:] + 9310
frame #4: 0x00007fff89359451 CoreData`-[NSManagedObjectModel(_NSManagedObjectModelPrivateMethods) initWithContentsOfOptimizedURL:] + 305
frame #5: 0x00007fff89358d7b CoreData`-[NSManagedObjectModel initWithContentsOfURL:] + 443
frame #6: 0x00007fff893e9519 CoreData`+[NSManagedObjectModel mergedModelFromBundles:] + 377
frame #7: 0x00007fff8ded7037 AppKit`-[NSPersistentDocument managedObjectModel] + 301
frame #8: 0x00007fff8ded70b3 AppKit`-[NSPersistentDocument managedObjectContext] + 75
frame #9: 0x00007fff8ded6e3f AppKit`-[NSPersistentDocument _persistentStoreCoordinator] + 18
frame #10: 0x00007fff8ded6b5d AppKit`-[NSPersistentDocument configurePersistentStoreCoordinatorForURL:ofType:modelConfiguration:storeOptions:error:] + 51
frame #11: 0x0000000100003193 BeanCounter`-[AccountDocument configurePersistentStoreCoordinatorForURL:ofType:modelConfiguration:storeOptions:error:] + 419 at AccountDocument.m:298
Судя по документации, реализация по умолчанию выглядит примерно так:
- (id)managedObjectModel
{
NSManagedObjectModel *result = [NSManagedObjectModel mergedModelFromBundles:nil];
return result;
}
Итак, чтобы немного отладить проблему, я переопределил этот метод следующим образом:
- (id)managedObjectModel
{
NSBundle *bundle = [NSBundle mainBundle];
NSURL *url = [bundle URLForResource:@"AccountDocument2" withExtension:@"momd"];
NSManagedObjectModel *result = [[[NSManagedObjectModel alloc] initWithContentsOfURL:url] autorelease];
return result;
}
(Спасибо Джеффу Ламарче за идею: http://iphonedevelopment.blogspot.com/2009/09/core-data-migration-problems.html).
И пакет, и URL-адрес указывают на ожидаемые мной места (и я последовал совету Маркуса Зарры по очистке проекта, чтобы в пакете приложения не было случайных пакетов .mom или .momd: Использование mergedModelFromBundles: и управление версиями (CoreData)). Тем не менее, приложение продолжает вылетать при загрузке модели с URL-адреса.
Я проверил, что AccountDocument2.xcdatamodeld - это пакет, который имеет две модели для управления версиями: AccountDocument 2.xcdatamodel и (исходный) AccountDocument.xcdatamodel. Во всплывающем меню «Версия базовой модели данных» в свойствах файла задано значение «AccountDocument 2».
Единственное различие между двумя моделями состоит в том, что одна сущность имеет дополнительный (и необязательный) атрибут. Насколько я понимаю, это квалифицирует модель для облегченной миграции.
Очевидно, я здесь что-то не так делаю, но понятия не имею, что именно. Любая помощь будет очень признательна ...
Обновление:
По предложению Мартина (и проверке документации NSPersistentDocument) я попытался использовать этот код для средства доступа:
- (id)managedObjectModel
{
static id sharedManagedObjectModel = nil;
if (sharedManagedObjectModel == nil) {
NSBundle *bundle = [NSBundle mainBundle];
NSURL *url = [bundle URLForResource:@"AccountDocument2" withExtension:@"momd"];
sharedManagedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:url];
}
return sharedManagedObjectModel;
}
По-прежнему происходит сбой…
Обновить
После некоторых предложений в Twitter я обновился до Xcode 4.3.2, но проблемы не исчезли.
ОБНОВЛЕНИЕ ЯРОСТИ
Я только что создал пакет модели с версией (AccountDocument2.xcdatamodeld), используя Xcode 4.2 на Snow Leopard. После сборки и запуска приложения все работает должным образом.
Затем я вернул пакет файлов AccountDocument2.xcdatamodeld обратно в Lion и Xcode 4.3.2. Когда я создаю и запускаю приложение, оно продолжает вылетать при загрузке ресурса .momd. Да, детки, это означает, что виноваты Xcode 4.3.x и компилятор модели данных (MOMC). Я не вижу другого пути, кроме как делать все свои сборки на Snow Leopard.
Я не из тех, кто использует Xcode 4, но когда мы оказываемся в ситуации, когда инструментальная цепочка не может создать непрозрачный файл (.mom и .momd) из непрозрачной спецификации (.xcdatamodel и .xcdatamodeld), это довольно сложно Будьте оптимистичны относительно состояния инструментов Mac и iOS. Смешно, что основной компонент этих платформ ломается до такой степени, что я не могу создавать и запускать свое приложение в последней версии SDK и инструментов разработчика.
Это дошло до этого обновления
Еще одно доказательство того, что это серьезная ошибка компилятора модели данных (MOMC) в Xcode 4.3.2: если я скопирую пакет .momd из папки ресурсов, созданной Xcode 4.2, в свой проект и добавлю их в сборку как файлы копирования этап сборки, приложение работает нормально.
Я также провел несколько тестов, в которых я удалил правила проверки и значения по умолчанию для атрибутов различных сущностей (на основе предложения Маркуса ниже). Без изменений, компилятор по-прежнему создает недопустимый .momd. Я также попытался создать модель с версией, в которой НИЧЕГО не изменилось: скомпилированный .momd продолжал давать сбой. Итак, все, что у вас есть в ваших текущих моделях (и данных, которые они представляют), является источником проблемы.
Также обратите внимание: эта ошибка не изолирована от NSPersistentDocument (как я изначально думал, когда задавал этот вопрос). Я могу вызвать сбой приложения, просто используя [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL]
.
На данный момент я буду редактировать / управлять версиями своих моделей с помощью Xcode 4.2 на Snow Leopard и перемещать скомпилированные ресурсы в Xcode 4.3.2 на Lion. Если вы каким-либо образом используете Core Data, я предлагаю вам делать то же самое, пока эта ошибка не будет устранена. Поверьте, вы потратите дни, пытаясь понять, что, черт возьми, происходит, если вы этого не сделаете.
Теперь, чтобы отправить радар…
Обновление радара
Я только что отправил этот радар:
http://www.openradar.me/11184500
Обновление "О, черт возьми, должно быть, лев"
Я только что загрузил и установил инструменты Xcode 4.2 для Lion с http://developer.apple.com/downloads. Пример приложения, используемого в радаре, по-прежнему дает сбой.
(Примечание: вы не можете установить Xcode 4.2.1, потому что срок действия сертификата, используемого для подписи DeveloperTools.pkg, истек. Только Xcode 4.2 будет работать.)
Если вы находитесь под соглашением о неразглашении, вы также обнаружите, что бета-инструменты тоже бесполезны.
Надеюсь, у вас есть копия Snow Leopard с Xcode 4.2, сидящая без дела: http://furbo.org/2012/03/28/vmware-for-developers/
Запросы на выборку WTF имеют отношение к версионным объектам и обновлению атрибутов
Через Эвадну Ву в Twitter:
https://twitter.com/#!/evadne/status/187625192342818818
И как она это сделала:
https://twitter.com/#!/evadne/status/187629091518816258
(Файлы .mom представляют собой двоичные списки.)
Корень проблемы - единственный запрос на выборку. Как это влияет на миграцию данных из одной модели в другую, предстоит выяснить инженеру Apple.
configurePersistentStoreCoordinatorForURL:::::
? В противном случае вы теряете копию, сделанную вами изstoreOptions
. - person Peter Hosey   schedule 04.04.2012@interface NSManagedObject (NSManagedObjectFetchBugApology) - (void)heyCraig:(id)in1 sorryAboutThat:(id)in2 mustHaveSlippedTheUnitTests:(id)in3 theRootCauseIsBothVerySimpleAndVeryComplicated:(id)in4 thanksForTheDetailedRadarWeOweYouABeerAtNextWWDCSeeYouThere:(id)in5; @end
- person Pierre Lebeaupin   schedule 05.04.2012