Основные данные - миграция по умолчанию (вручную) - PullRequest
9 голосов
/ 07 февраля 2012

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

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

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

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

Атрибут

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

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

- (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 тем, чем он был (интергер 16, сохранив два других изменения в модели. Легкая миграция работала просто отлично.

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

                      ## EDIT ##

Хорошо, мне нужно докопаться до сути, я скачал приложение, которое Михай собрал (спасибо!), И начал с ним баловаться. Я изменил постоянный координатор хранилища, чтобы он соответствовал тому, что у меня есть, чтобы «Миграция по умолчанию» была такой

- (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] *** Завершение работы приложения из-за необработанного исключения «NSInvalidArgumentException», причина: «Недопустимый тип значения для атрибута: property =" reportId »; желаемый тип = NSString; заданный тип = __NSCFNumber; значение = 1. '

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

   Report = "(<NSEntityDescription: 0x1708d0>) name Report, managedObjectClassName Report, renamingIdentifier Report, isAbstract 0, superentity name (null), properties {\n    action = \"(<NSAttributeDescription: 0x170a30>), 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 = \"(<NSAttributeDescription: 0x1709e0>), 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 = \"(<NSAttributeDescription: 0x170a80>), 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 = \"(<NSAttributeDescription: 0x170ad0>), 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 = \"(<NSAttributeDescription: 0x170990>), 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}, {

РЕДАКТИРОВАТЬ 2

Дошло до того, что у меня появилось «NSInvalidArgumentException», причина: «Несоответствие между отображением и моделями источника / назначения» - для моделей как источника, так и назначения и моделей отображения все выглядит так, как должно. Я собираюсь сдаться и хочу потерять данные в этой сущности отчета. Есть ли способ сделать это?

РЕДАКТИРОВАТЬ 3

Итак, просто чтобы попробовать, я откатил свою модель, где она была до всего этого безумия, создал новую версию, в которой я сделал только одно изменение - упал одно поле. И тогда я создал модель отображения и попробую использовать ее - Та же ошибка Несоответствие между моделями сопоставления и моделями источника / назначения - похоже, что сгенерированная модель сопоставления как-то плоха, но, глядя на нее - я не вижу никаких проблем.

Ответы [ 2 ]

23 голосов
/ 24 февраля 2012

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

Я программно исправил их, и произошла миграция.

 NSURL *fileURL = [[NSBundle mainBundle] URLForResource:@"Model" withExtension:@"cdm"];
 NSMappingModel *mappingModel = [[NSMappingModel alloc] initWithContentsOfURL:fileURL];

 NSArray *newEntityMappings = [NSArray arrayWithArray:mappingModel.entityMappings];
 for (NSEntityMapping *entityMapping in newEntityMappings) {

[entityMapping setSourceEntityVersionHash:[sourceModel.entityVersionHashesByName     valueForKey:entityMapping.sourceEntityName]];
[entityMapping setDestinationEntityVersionHash:[destinationModel.entityVersionHashesByName valueForKey:entityMapping.destinationEntityName]];
        }
mappingModel.entityMappings = newEntityMappings;

        BOOL ok = [migrationManager migrateStoreFromURL:sourceStoreURL
                                                   type:sourceStoreType
                                                options:nil
                                       withMappingModel:mappingModel
                                       toDestinationURL:destinationStoreURL
                                        destinationType:destinationStoreType
                                     destinationOptions:nil
                                                  error:&error];
4 голосов
/ 07 февраля 2012

С помощью я получил от этот вопрос я решил вашу проблему.

Я собрал демонстрационное приложение, основанное на стандартном шаблоне мастер / подробности с основными данными.При первом запуске убедитесь, что у вас выбрана модель «TestData» в «TestData.xcdatamodeld».Добавьте несколько строк, затем перейдите к «TestData 2.xcdatamodel», и миграция внесет необходимые изменения.

Демонстрационное приложение можно загрузить с здесь

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...