核心数据 – 默认迁移(手动)

我已经读过所有可能的博客,所以就这个问题上发表 – 但仍然不知道发生了什么事情。 我也读过这个,但仍然没有运气 – 他们的指导默认迁移种清除,但在我的情况不起作用。 我对iOS开发比较新,所以要温柔:)

这是情况:在我的应用程序(iOS)中称为报表的实体,需要进行以下更改:

数据属性 – 删除

标题属性 – 添加

reportId属性需要从整数16更改为string。 这是什么原因造成我的问题。 我从当前版本创build了我的数据模型的新版本并修改了属性。

首先这里是从应用程序的一些方法:

- (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,在模型中保留其他两个变化。轻量级迁移工作得很好。

好吧,我想,它可能需要手动映射,以处理数据types的变化。 所以,我已经创build了映射模型(其中我试图设置reportId“”和source.reportId),closures轻量级迁移。 由于我是新来的,我已经决定采取婴儿的步骤,不要让这个reportId Int>string改变,然后testing我的映射。 它没有工作。 原因相同=无法find迁移的映射模型。 我试图将reportId更改为string,因为它应该是 – 相同的结果。 几乎看起来我的映射模型完全被忽略了。 事实上,我试图删除它 – 相同的结果相同的错误。 我到底在想什么?

  ## EDIT ## 

好的,我需要深入了解这一点,我已经下载了Mihai已经放在一起的应用(谢谢!),并开始玩弄它。 我修改了持久性存储协调器,以匹配“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; } 

而且我得到了对我来说完全有意义的错误。 它基本上find了正确的映射模型,并尝试匹配它,并给出了非常有效的错误。 2012-02-07 10:47:39.246testing数据[2008:707] ***由于未捕获的exception'NSInvalidArgumentException',原因:'不可接受的属性types的值:属性=“reportId”; 所需的types= NSString; 给定types= __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',原因:'映射和源/目的地模型之间不匹配' – po源和目标模型和映射模型,一切看起来像它应该。 我即将放弃并愿意放弃该报告实体中的数据。有没有办法做到这一点?

编辑3

所以,只是尝试一下,我已经把我的模型回滚到了所有这些疯狂之前,创造了新的版本,我只做了一个改变 – 删除了一个字段。 然后我创build了映射模型并尝试使用它。 – 相同的错误映射和源/目标模型之间不匹配 – 它看起来像生成的映射模型是不好的,但看着它 – 我没有看到任何问题。

在这个问题的帮助下,我解决了你的问题。

我已经将基于默认主/从模板的演示应用与核心数据放在一起。 当第一次运行时,确保在“TestData.xcdatamodeld”中select了“TestData”模型。 添加一些行,然后移动到“TestData 2.xcdatamodel”,迁移将作出适当的更改。

演示应用程序可以从这里下载

如果你没有find答案,我可以build议小动作。 首先,idk为什么发生这种情况,但源模型,目标模型和映射模型对于相同的实体具有不同的versionHashes值。

我programmaticaly纠正他们和迁移发生。

  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];