在 NSPersistentDocument 上启用核心数据的自动轻量级迁移
Posted
技术标签:
【中文标题】在 NSPersistentDocument 上启用核心数据的自动轻量级迁移【英文标题】:Enable Automatic Lightweight Migration of Core Data on NSPersistentDocument 【发布时间】:2011-05-16 00:14:42 【问题描述】:ALM 很棒。但我无法让它在使用核心数据和 NSDocument 的项目上工作。默认情况下似乎禁用了 ALM。
很好。对于任何普通项目,您需要在此行的字典中添加两个适当的选项:
if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:options error:&error])
...但是当使用带有 NSD 的 CD 时,该行不存在(NSPersistentDocument 隐藏了详细信息,我看不到如何修改它们)。
以下方法似乎提供了希望:
configurePersistentStoreCoordinatorForURL:ofType:modelConfiguration:storeOptions:error:
...邮件列表中的一些人(从 4 年前开始)报告成功覆盖该方法,更改选项字典,然后在“super”上重新调用它。可悲的是,这对我不起作用。如果您有类似的问题,我建议您先尝试一下 - 如果它仍然不起作用,请回到这里 :)
【问题讨论】:
【参考方案1】:从头开始制作一个新的 Cored-Data-with-NSDocument 项目,我尝试了最初不起作用的方法,这次效果很好:
-(BOOL)configurePersistentStoreCoordinatorForURL:(NSURL *)url ofType:(NSString *)fileType modelConfiguration:(NSString *)configuration storeOptions:(NSDictionary *)storeOptions error:(NSError **)error
NSMutableDictionary *newOptions = [NSMutableDictionary dictionaryWithDictionary:storeOptions];
[newOptions setValue:@"YES" forKey:NSMigratePersistentStoresAutomaticallyOption];
[newOptions setValue:@"TRUE" forKey:NSInferMappingModelAutomaticallyOption];
return [super configurePersistentStoreCoordinatorForURL:url ofType:fileType modelConfiguration:configuration storeOptions:newOptions error:error];
【讨论】:
【参考方案2】:NB:我怀疑我的问题的根本原因是 Xcode4 不正确更新了它使用的私有哈希而不是版本号来跟踪数据模型版本。可能我不小心添加了一些东西,然后删除了它,它改变了哈希值——我原来的模型非常简单,很容易用肉眼比较,没有任何区别。
此外,更一般地说,问题在于 Xcode4 仍然 不能正确处理 CoreData 项目 - 默认情况下它会将 CoreData 模型创建为“版本化”(对 Xcode3 的重大改进,这注定总是创建无用的模型),但它仍然没有对模型中的更改进行任何处理 - 您必须在保存任何更改之前手动记住更新版本(否则您的所有项目迁移都将失败,永远,没有出路)。
此外,一旦出现问题,我找不到任何“正确”的解决方案 - Apple 的核心数据库中缺少太多的部分。基本上:据我所知,NSPersistentDocument 不完整,不受支持。
最后,我采用了以下 BRUTAL 解决方法:指示所有使用旧版本的人手动编辑 CoreData 存储以声明他们正在运行当前版本。
这 100% 有效,因为与 CoreData 不同,我的应用程序可以智能地更正导入时任何明显丢失的数据。这很简单,但 CoreData 不允许你说“是的,我已经完成了。没关系。继续打开文件!”
-
在旧版本中:“另存为 XML”
为他们提供了新的标题以复制/粘贴到文件顶部。注意:Apple 使用哈希而不是版本号,这使得这看起来很可怕,即使它不是。我不明白为什么 Apple 会忽略他们自己的版本系统而使用哈希值?
在新版本中:打开更新后的文件
在新版本中:“保存”
...因为我重写了 NSManagedObject 方法:
-awakeFromInsert
并修复任何不正确/缺失的数据,上面的步骤 3 和 4 “自动”更新数据。
我知道“正确”的方法是创建一个映射模型,但在大多数情况下这太过分了……而且 Apple 一开始就拒绝加载旧数据。所以,Core Data 甚至拒绝让我更正数据——尽管我的代码很乐意这样做。
(所有旧项目都已正确导入和导出 - 没问题)
恕我直言:CoreData 确实需要对 Apple 进行一些重新设计,以修复他们第一次没有考虑到的所有边缘情况。
注意:快速警告:确保不要更改 awakeFromFetch 中的任何 CoreData 变量 - Apple 在调用该方法之前暂时禁用更改跟踪(这有点可笑 - 它使该方法与所有其他“ awakeFrom*" 方法)。
Apple 的建议:在 awakeFromFetch 中,决定要更改的内容,然后将其打包并使用如下内容:
[self performSelector:@selector(myAwakeFromFetchFixItemX:) withObject:X afterDelay:0.01];
...只是想我会为尝试此操作的任何人添加该内容-否则您的导入将正常工作,但您的导出将默默地无法包含固定数据!
【讨论】:
以上是关于在 NSPersistentDocument 上启用核心数据的自动轻量级迁移的主要内容,如果未能解决你的问题,请参考以下文章
NSPersistentDocument 中的 NSTextView 在失去第一响应者之前不会更新脏标志
NSPersistentDocument 和 NSArrayController 与 MagicalRecord
撤消管理器未与 NSPersistentDocument 保持同步
在 NSPersistentDocument 上启用核心数据的自动轻量级迁移