Core Data - Default Migration (Manual)

Я прочитал все возможные блоги и сообщения SO на эту тему - но все еще не уверен, что происходит. Я также прочитал это, но все еще не повезло - их руководство по миграции по умолчанию вроде как понятно, но не работает в моей ситуации. Я относительно новичок в разработке iOS, так что будьте мягче :)

Вот ситуация: в сущности под названием Report в моем приложении (iOS) должны произойти следующие изменения:

атрибут data - удален

атрибут title - добавлен

атрибут reportId должен быть изменен с Integer 16 на String. Это то, что вызывает мои проблемы. Я создал новую версию своей модели данных на основе текущей и изменил атрибуты.

Сначала вот некоторые методы из приложения:

- (NSManagedObjectModel *)managedObjectModel
{
    if (__managedObjectModel != nil)
    {
        return __managedObjectModel;
    }
    NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"App" withExtension:@"momd"];
    __managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];    
    return __managedObjectModel;
}

и затем

/**
 Returns the persistent store coordinator for the application.
 If the coordinator doesn't already exist, it is created and the application's store added to it.
 */
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
    if (__persistentStoreCoordinator != nil)
    {
        return __persistentStoreCoordinator;
    }

    NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"App.sqlite"];
    NSError *error = nil;

    __persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];

    NSLog(@"Which Current Version is our .xcdatamodeld file set to? %@", [[self managedObjectModel] versionIdentifiers]);
    NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:  
                             [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption, 
//Commented for manual migration [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption,  
                             nil];  


    if (![__persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error])
    {

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

    return __persistentStoreCoordinator
}

Сначала я попробовал легкую миграцию. Она не удалась

reason=Can't find mapping model for migration

Затем я сделал следующее, просто чтобы попробовать: вернул атрибут reportId к тому, что было (interger 16, сохранив два других изменения в модели. Легкая миграция сработала просто отлично.

Хорошо, подумал я, вероятно, необходимо ручное отображение для обработки изменения типа данных. Итак, я создал модель отображения (в которой я пытался установить reportId и в "", и в source.reportId), отключил легкую миграцию. Поскольку я новичок в этом деле, я решил сделать маленькие шаги и пока не менять reportId Int > String и протестировать мое отображение. И это не сработало. С той же причиной = Невозможно найти модель отображения для миграции. Я попытался изменить reportId на String, как и должно быть - тот же результат. Мне кажется, что моя модель отображения полностью игнорируется. На самом деле я пытался удалить ее - тот же результат, та же ошибка. Что, черт возьми, я здесь упускаю?

                      ## EDIT ##

Хорошо, мне нужно разобраться с этим, я скачал приложение, которое создал Михай (спасибо!) и начал играть с ним. Я изменил persistent store coordinator, чтобы соответствовать тому, что у меня есть для "Default Migration", чтобы было так

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
    if (__persistentStoreCoordinator != nil)
    {
        return __persistentStoreCoordinator;
    }

    NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"TestData.sqlite"];

    NSError *error = nil;
    __persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];

    NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:  
                             [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption, 
                                                       nil]; 

    if (![__persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error])
    {
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    }    

    return __persistentStoreCoordinator;
}

И я получил ошибку, которая полностью имеет смысл для меня. По сути, он нашел нужную модель отображения и попытался ее сопоставить, выдав вполне корректную ошибку. 2012-02-07 10:47:39.246 TestData[2008:707] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Unacceptable type of value for attribute: property = "reportId"; desired type = NSString; given type = __NSCFNumber; value = 1. '

Где в моем случае у меня есть дамп, который выглядит так (только небольшая часть лога) :

   Report = "() name Report, managedObjectClassName Report, renamingIdentifier Report, isAbstract 0, superentity name (null), properties {\n    action = \"(), name action, isOptional 1, isTransient 0, entity Report, renamingIdentifier action, validation predicates (\\n), warnings (\\n), versionHashModifier (null)\\n userInfo {\\n}, attributeType 100 , attributeValueClassName NSNumber, defaultValue 0\";\n    data = \"(), name data, isOptional 1, isTransient 0, entity Report, renamingIdentifier data, validation predicates (\\n), warnings (\\n), versionHashModifier (null)\\n userInfo {\\n}, attributeType 700 , attributeValueClassName NSString, defaultValue (null)\";\n    reportId = \"(), name reportId, isOptional 1, isTransient 0, entity Report, renamingIdentifier reportId, validation predicates (\\n), warnings (\\n), versionHashModifier (null)\\n userInfo {\\n}, attributeType 100 , attributeValueClassName NSNumber, defaultValue 0\";\n    timestamp = \"(), name timestamp, isOptional 1, isTransient 0, entity Report, renamingIdentifier timestamp, validation predicates (\\n), warnings (\\n), versionHashModifier (null)\\n userInfo {\\n}, attributeType 900 , attributeValueClassName NSDate, defaultValue (null)\";\n    type = \"(), name type, isOptional 1, isTransient 0, entity Report, renamingIdentifier type, validation predicates (\\n), warnings (\\n), versionHashModifier (null)\\n userInfo {\\n}, attributeType 100 , attributeValueClassName NSNumber, defaultValue 0\";\n}, subentities {\n}, userInfo {\n}, versionHashModifier (null)";
}, fetch request templates {
}, reason=Can't find mapping model for migration}, {

EDIT 2

Дошел до точки, где у меня 'NSInvalidArgumentException', reason: 'Mismatch between mapping and source/destination models' - по обеим моделям источника и назначения и модели отображения, все выглядит как должно. Я уже почти сдался и готов потерять данные в этом отчете... Есть ли какой-нибудь способ сделать это?

EDIT 3

Итак, просто чтобы попробовать, я откатил свою модель туда, где она была до всего этого безумия, создал новую версию, в которой я сделал только одно изменение - удалил одно поле. Затем я создал модель отображения и попытался использовать ее. - Та же ошибка Mismatch between mapping and source/destination models - похоже, что сгенерированная модель отображения как-то не так, но посмотрев на нее, я не увидел никаких проблем.

9
задан Alex Volovoy 8 February 2012 в 16:23
поделиться