Упрощенная миграция NSPersistentDocument

Я пытаюсь выполнить упрощенную миграцию хранилища 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)

Когда я запускаю приложение, оно дает сбой в реализации NSPersistentDocument -managedObjectModel:

* 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;
}

Все еще происходит сбой…

Обновление

После некоторые предложения в Твиттере, я обновился до Xcode 4.3.2, но проблемы сохраняются.

RAGE UPDATE

Я только что создал пакет версии модели (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

О, дерьмо, это должно быть обновление Lion

Я только что загрузил и установил Xcode 4.2 для инструментов Lion из http://developer.apple.com/downloads. Пример приложения, используемого в Radar, по-прежнему дает сбой.

(Примечание: вы не можете установить Xcode 4.2.1, поскольку срок действия сертификата, использованного для подписи DeveloperTools.pkg, истек. Подойдет только Xcode 4.2.)

Если вы находитесь под соглашением о неразглашении, вы также обнаружите, что бета-инструменты также бесполезны.

Надеюсь, у вас есть копия Snow Leopard с Xcode 4.2: http://furbo.org/2012/03/28/vmware-for-developers/

WTF Do Fetch Requests Have To Обновление «Что делать с версионными сущностями и атрибутами»

Через Эвадне Ву в Твиттере:

https://twitter.com/#!/evadne/status/187625192342818818

И как она это сделала:

https:/ /twitter.com/#!/evadne/status/187629091518816258

(файлы .mom представляют собой двоичные списки.)

Корень проблемы — один запрос на выборку. Как это отразится на переносе данных из одной модели в другую, должен выяснить инженер Apple.

45
задан Community 23 May 2017 в 11:45
поделиться