首页 > 解决方案 > +[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 认为它是哪个版本的模型?

标签: ioscocoacore-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 时,你会发现额头拍打。如果没有,请给我们一些关于您粘贴的代码的更多上下文,可能有人可以提供帮助。


推荐阅读