ios - +[NSManagedObjectModel mergeModelFromBundles::forStoreMetadata:] 总是返回 nil
问题描述
我有一个包含 15 个版本的核心数据模型。它的代码可以在发布时从当前商店的版本逐步迁移到最新版本。
关键是呼吁
NSDictionary* options = @{ NSMigratePersistentStoresAutomaticallyOption : @true,
NSInferMappingModelAutomaticallyOption : @true };
NSDictionary* sourceMetadata = [NSPersistentStoreCoordinator
metadataForPersistentStoreOfType: inType
URL: inSourceStore
options: options
error: outError];
NSManagedObjectModel* model = [NSManagedObjectModel mergedModelFromBundles: @[ [NSBundle bundleForClass: [self class]] ]
forStoreMetadata: inSourceMetadata];
但这总是返回零,我不知道为什么。现有商店是版本 14,新模型是版本 15。
现在,对模型的最后一次更改相当简单(添加了几个可选字段),所以我原以为它可以自动推断映射,但这不起作用,所以我从版本 14 添加了一个映射模型到版本 15 使用 Xcode 的助手,并且没有进行任何更改。
知道为什么它返回零,或者我可以做些什么来进一步调查?
同样,当我说“版本 14”时,我指的是.xcdatamodel
文件的顺序编号。有什么方法可以查看实际存储并确定 Core Data 认为它是哪个版本的模型?
解决方案
好吧,首先,您似乎知道自己在做什么,经历了 14 次核心数据迁移等等。所以我认为你应该注意一些愚蠢的打额头的错误。
确保[NSBundle bundleForClass: [self class]]
返回预期的包,其中包含一个目录Contents/Resources/YourModelName.momd
,并且该目录包含所有必需的.mom
文件(每个版本一个)和一个VersionInfo.plist
文件。我的构建还包含一个.omo
仅适用于最新版本的文件。
现在我来回答你的第二个问题,这确实可以帮助你回答你的第一个问题。
在该VersionInfo.plist
文件中,您将找到一个名为 的字典NSManagedObjectModel_VersionHashes
,该字典又包含子字典,每个版本都有一个键。每个版本子字典都包含每个实体名称和值的键,它是该版本中该实体的属性和关系的 32 字节(256 位)散列。我们称这些为模型哈希。
sqlite3
现在使用 SQLite 查看器或命令行工具打开一个商店数据库文件。在该数据库中,除了模型中每个实体的一个表之外,您将看到一个以Z_METADATA
一行和三列命名的表。命名列的值Z_PLIST
被键入为二进制数据的 blob。将该数据复制到一个文件中,用扩展名命名.plist
,双击它,它会在您最喜欢的 plist 编辑器中打开,因为该数据实际上是一个文本字符串,表示 XML 格式的 Apple 属性列表。它的键值NSStoreModelVersionHashes
实际上是一个子字典,就像VersionInfo.plist
文件中的子字典一样。让我们称之为商店哈希. 32 字节(256 位)版本哈希是 Base64 编码的。(有 44 个 Base64 字符。由于每个 Base64 字符代表 6 位,因此 44 个字符最多可以表示 44*6 = 264 位。)
最后,回答你的第二个问题,storeMetadata
传递给+[NSManagedObjectModel mergedModelFromBundles:forStoreMetadata:]
实际上是Z_METADATA
来自商店,其中包含那些商店哈希。 +[NSManagedObjectModel mergedModelFromBundles:forStoreMetadata:]
将这些存储散列与传入的每个候选数据模型的模型散列bundle
进行比较,并返回其模型散列与所有实体的存储散列匹配的模型,任何一方都没有额外的不匹配实体。
因此,您会发现手动进行比较有点乏味。但可能在探索这些 plists 时,你会发现额头拍打。如果没有,请给我们一些关于您粘贴的代码的更多上下文,可能有人可以提供帮助。
推荐阅读
- c++ - 我已经通过了该问题的所有测试用例,甚至通过了 Udebugg 上的所有测试用例,并且仍然获得了关于 UVA 在线法官的 WA 判决
- node.js - Twilio Outbound Call API - 如何在呼出电话接收者的语音邮件中放置记录?
- jquery - 如何将变量添加到 URL
- c# - 在不同线程上运行的两个实例交叉并复制了不应具有的数据
- java - TIFF 图像上的水印
- flutter - 如何使用 StreamBuilder 管理块引发的异常?
- swift - Swift 属性包装器可以引用其包装的属性所有者吗?
- android - Android SDK 播放器自动化
- android - 从普通 Skype 应用程序呼叫 Skype for business 帐户
- java - 如何使用 Selenium Webdriver 从 Angular 应用程序中获取所有 WebElement?