【发布时间】:2012-02-28 12:22:14
【问题描述】:
我已经阅读了所有可能的博客和关于该主题的 SO 帖子 - 但仍然不确定发生了什么。 我也读过this,但仍然没有运气——他们的默认迁移指南很清楚,但在我的情况下不起作用。 我对 iOS 开发比较陌生,所以要温柔:)
情况如下: 在我的应用 (iOS) 中名为 Report 的实体上,需要进行以下更改:
数据属性 - 已删除
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 属性恢复为原来的状态(整数 16,保留模型中的其他两个更改。轻量级迁移工作得很好。
好的,我想,它可能需要手动映射才能处理数据类型更改。 因此,我创建了映射模型(在其中我尝试将 reportId 设置为 "" 和 source.reportId ),关闭了轻量级迁移。因为我是新手,所以我决定采取一些小步骤,不要让这个 reportId Int > String 改变并测试我的映射。它没有用。同理=找不到迁移的映射模型。我试图将 reportId 更改为 String 应该是 - 结果相同。在我看来,我的映射模型几乎被完全忽略了。事实上,我试图删除它——同样的结果同样的错误。 我到底在想什么?
## EDIT ##
好的,我需要深入了解这一点,我已经下载了 Mihai 制作的应用程序(谢谢!)并开始使用它。 我已经修改了持久存储协调器以匹配我为“默认迁移”所拥有的任何内容
- (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”而终止应用程序,原因:“属性值的不可接受类型:属性 =“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
所以,为了尝试一下,我将模型回滚到所有这些疯狂之前的位置,创建了新版本,其中我只进行了一项更改 - 删除了一个字段。然后我创建了映射模型并尝试使用它。 - 映射和源/目标模型之间的相同错误不匹配 - 看起来生成的映射模型在某种程度上是不好的,但是看着它 - 我没有发现任何问题。
【问题讨论】:
-
嗨。我相信你需要为你的托管对象专门化一个 NSEntityMigrationPolicy,并在你的映射模型中设置它的名称。你做到了吗?
标签: ios core-data migration versioning