核心数据 - 默认迁移(手册) [英] Core Data - Default Migration ( Manual )

查看:23
本文介绍了核心数据 - 默认迁移(手册)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经阅读了所有可能的博客和关于这个主题的帖子 - 但仍然不确定发生了什么.我还阅读了 this 但仍然没有运气 - 他们的默认迁移指南很清楚,但在我的情况下不起作用.我对 iOS 开发比较陌生,所以要温柔:)

情况如下:在我的应用程序 (iOS) 中名为 Report 的实体上,需要进行以下更改:

数据 属性 - 已删除

title 属性 - 已添加<​​/p>

reportId 属性需要从 Integer 16 更改为 String.这就是导致我出现问题的原因.我确实从当前的数据模型中创建了新版本的数据模型并修改了属性.

首先是应用程序中的一些方法:

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

然后

/**返回应用程序的持久存储协调器.如果协调器尚不存在,则会创建它并将应用程序的商店添加到其中.*/- (NSPersistentStoreCoordinator *)persistentStoreCoordinator{if (__persistentStoreCoordinator != nil){返回 __persistentStoreCoordinator;}NSURL *storeURL = [[self applicationDocumentsDirectory] ​​URLByAppendingPathComponent:@"App.sqlite"];NSError *error = nil;__persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];NSLog(@"我们的 .xcdatamodeld 文件设置为哪个当前版本?%@", [[self managedObjectModel] versionIdentifiers]);NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,//注释手动迁移 [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption,零];if (![__persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error]){NSLog(@"未解决的错误 %@, %@", error, [error userInfo]);中止();}返回 __persistentStoreCoordinator}

首先,我尝试了轻量级迁移.它失败了

reason=找不到迁移的映射模型

然后我做了以下尝试:使 reportId 属性恢复原状(整数 16,在模型中保留其他两个更改.轻量级迁移工作得很好.

好吧,我想,它可能需要手动映射才能处理数据类型更改.因此,我创建了映射模型(在其中我尝试将 reportId 设置为 "" 和 source.reportId ),并关闭了轻量级迁移.由于我是新手,因此我决定采取一些措施,暂时不要更改此 reportId Int > String 并测试我的映射.它没有用.同理=找不到迁移的映射模型.我试图将 reportId 更改为 String ,因为它应该是 - 结果相同.在我看来,我的映射模型几乎被完全忽略了.事实上,我试图删除它——同样的结果同样的错误.我到底错过了什么?

 ## 编辑 ##

好的,我需要深入了解,我已经下载了 Mihai 组装的应用程序(谢谢!)并开始尝试使用它.我已经修改了持久存储协调器以匹配我对默认迁移"的所有内容

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator{if (__persistentStoreCoordinator != nil){返回 __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,零];if (![__persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error]){NSLog(@"未解决的错误 %@, %@", error, [error userInfo]);中止();}返回 __persistentStoreCoordinator;}

我有一个对我来说完全有意义的错误.它基本上找到了正确的映射模型并尝试匹配它并给出了非常有效的错误.2012-02-07 10:47:39.246 TestData[2008:707] *** 由于未捕获的异常NSInvalidArgumentException"而终止应用程序,原因:不可接受的属性值类型:property =reportId";所需类型 = NSString;给定类型 = __NSCFNumber;值 = 1.'

在我的情况下,我的转储看起来像这样(只是日志的一小部分):

 Report = "() name Report, managedObjectClassName Report, renamingIdentifier Report, isAbstract 0, superentity name (null), properties {
 action = "(), name action, isOptional 1, isTransient 0, entity Report, renamingIdentifier action, 验证谓词 (\n), 警告 (\n), versionHashModifier (null)\n userInfo {\n}, attributeType 100 , attributeValueClassNameNSNumber, defaultValue 0";
 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)";
 reportId = "(), name reportId, isOptional 1,isTransient 0, 实体报告, renamingIdentifier reportId, 验证谓词 (\n), 警告 (\n), versionHashModifier (null)\n userInfo {\n}, attributeType 100 , attributeValueClassName NSNumber, defaultValue 0";
 timestamp = "(), name timestamp, isOptional 1, isTransient 0, entity报告、renamingIdentifier 时间戳、验证谓词 (\n)、警告 (\n)、versionHashModifier (null)\n userInfo {\n}、attributeType 900、attributeValueClassName NSDate、defaultValue (null)";
 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";
}, subentities {
}, userInfo {
}, versionHashModifier (null)";}, 获取请求模板{}, reason=找不到迁移的映射模型}, {

编辑 2

到了我有NSInvalidArgumentException"的地步,原因:映射和源/目标模型之间不匹配"-源和目标模型以及映射模型,一切看起来都应该如此.我即将放弃并愿意丢失该报告实体中的数据.. 有什么办法吗?

编辑 3

所以,只是为了尝试一下,我已经回滚了我的模型,在所有这些疯狂之前的地方,创建了新版本,其中我只做了一个更改 - 删除了一个字段.然后我创建了映射模型并尝试使用它.- 相同的错误 映射和源/目标模型之间的不匹配 - 看起来生成的映射模型在某种程度上很糟糕,但看着它 - 我没有看到任何问题.

解决方案

在我从 这个问题 我必须解决你的问题.

我已经将一个基于默认主/细节模板和核心数据的演示应用程序放在一起.第一次运行时,请确保在TestData.xcdatamodeld"中选择了TestData"模型.添加一些行,然后移至TestData 2.xcdatamodel",迁移将进行适当的更改.

可以从此处

下载演示应用程序

i've read all possible blogs and SO post on the subject - but still not sure what's going on. I've also read this but still no luck - their guide to Default migration kind of clear but doesn't work in my situation . I'm relatively new to iOS development, so be gentle :)

Here is the situation: on the entity called Report in my app (iOS), following changes need to happen:

data attribute - deleted

title attribute - added

reportId attribute need to be changed from Integer 16 to String. This is what causing my problems. I did created new version of the my data model from my current one and modifying attributes.

First here is some methods from the app:

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

and then

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

First i've tried lightweight migration. It failed with

reason=Can't find mapping model for migration

Then i did the following just to try: made reportId attribute back to what it was (interger 16, keeping other two changes in the model. Lightweight migration worked just fine.

Ok, i thought, it probably need to have manual mapping in order to handle data type change. So, i've created mapping model ( in which i've tried to set reportId to both "", and source.reportId ), turned off lightweight migration. Since i'm new to this, i've decided to take baby steps and don't make this reportId Int > String change just yet and test my mapping. And it didn't work. With same reason=Can't find mapping model for migration. I've tried to change reportId to String as it should be - same result. It almost looks to me that my mapping model is completely ignored. In fact i've tried to delete it - same result same error. What the hell i'm missing here ?

                      ## EDIT ##

Ok, i need to get to the bottom of this, I've downloaded the app that Mihai had put together ( thanks ! ) and started to play around with it. I've modified persistent store coordinator to match whatever i have for "Default Migration" to be this

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

And i've got the error that totally make sense to me. It basically found right mapping model and try to match it and gave very valid error. 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.'

Where in my case i have dump that looks like this ( just a small part of the log ) :

   Report = "(<NSEntityDescription: 0x1708d0>) name Report, managedObjectClassName Report, renamingIdentifier Report, isAbstract 0, superentity name (null), properties {
    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";
    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)";
    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";
    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)";
    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";
}, subentities {
}, userInfo {
}, versionHashModifier (null)";
}, fetch request templates {
}, reason=Can't find mapping model for migration}, {

EDIT 2

Got to the point where i have 'NSInvalidArgumentException', reason: 'Mismatch between mapping and source/destination models' - po both source and destination models and mapping models, everything looks like it should. I'm about to give up and willing to loose the data in that Report entity.. Is there any way of doing it ?

EDIT 3

So, just to try things out, i've rollback my model where it was before all this madness, created new version in which i've made only one change - dropped one field. And then i've created mapping model and try to use it. - Same error Mismatch between mapping and source/destination models - it looks like generated mapping model is bad somehow, but looking at it - i didn't see any issues.

解决方案

With the help i got from this question i got to solve your issue.

I have put together a demo app based on the default master/detail template with core data. When run it first time, make sure you have the "TestData" model selected in "TestData.xcdatamodeld". Add some rows, then move to "TestData 2.xcdatamodel" and the migration will make the proper changes.

The demo app can be downloaded from here

这篇关于核心数据 - 默认迁移(手册)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆