如果我已经发布的 v1 没有版本化的 Core Data 模型,我可以使用“自动轻量级迁移”吗?
Posted
技术标签:
【中文标题】如果我已经发布的 v1 没有版本化的 Core Data 模型,我可以使用“自动轻量级迁移”吗?【英文标题】:Can I use "Automatic Lightweight Migration" if my already release v1 didn't have a versioned Core Data model? 【发布时间】:2011-09-21 09:09:24 【问题描述】:如果是,是否对我需要应用的记录步骤进行了任何更改?
【问题讨论】:
已经接受了这一点,但在实施方面有一个问题,我认为这可能是它自己的问题,所以我把它放在这里...***.com/questions/7624502/… 仍然感谢任何帮助一。 【参考方案1】:您不仅可以做到这一点,从某种意义上说,这是您做到这一点的唯一方法。来自Apple Documentation,“要创建版本化模型,请从普通模型开始......”
您的 v1 有一个普通型号。只要您拥有该模型,并按照该教程中链接的步骤创建版本化模型,轻量级迁移就可以工作 - 如果您的迁移满足通常的轻量级迁移要求。轻量级迁移发生在您的 v2 应用程序(或 v1.1 或其他)中。 v1 应用程序中的数据模型基本上没有相关性。 Core Data 需要的是找到新的 v2 应用程序具有与本地设备上的 Core Data 存储中找到的数据模型相匹配的数据模型副本,并且具有描述您希望如何存储数据的新数据模型从现在开始。如果所需的更改满足轻量级迁移的要求,那么它就会这样做。
这些要求是什么?来自the Apple documentation on Lightweight Migration:
要执行轻量级迁移,Core Data 需要能够找到 源和目标托管对象在运行时自行建模。 (Core Data 搜索 NSBundle 的 allBundles 返回的包和 allFrameworks 方法。)然后它必须分析架构更改以 持久实体和属性并生成推断映射 模型。为了使 Core Data 能够做到这一点,更改必须适合 明显的迁移模式,例如:
• 简单添加新属性 • 非可选属性变为可选 • 一个可选属性变为非可选属性,并定义一个 默认值。
如果您重命名实体或属性,您可以设置 将目标模型中的标识符重命名为 源模型中的相应属性或实体。你通常 使用 Xcode 数据建模工具设置重命名标识符,(对于 一个 NSEntityDescription 或一个 NSPropertyDescription 对象)。在 Xcode,重命名标识符在 Detail 的 User Info 面板中 版本哈希修饰符下方的窗格(请参阅 Xcode 中的浏览器视图 核心数据工具)。您还可以使用在运行时设置标识符 设置重命名标识符:。比如处理
• 将实体 Car 重命名为 Automobile, • 重命名汽车的颜色 属性为paintColor
您将在之后包含以下代码 加载目标数据模型,然后尝试打开 存储文件:
NSEntityDescription *automobile = [[destinationModel entitiesByName] objectForKey:@"Automobile"]; [automobile setRenamingIdentifier:@"Car"]; NSPropertyDescription *paintColor = [[automobile attributesByName] objectForKey:@"paintColor"]; [paintColor setRenamingIdentifier:@"color"];
总之,您没有错过这艘船,现在使用 Core Data 的这些功能还为时不晚。 :) 为了回答您的具体问题,您无需更改文档中列出的标准步骤。
稍后更新 根据您对另一个答案的评论的进一步想法,您说:
所以只是为了确认,我不必在 XCode 中回溯我的核心数据 模型到它看起来像一个 v1 然后版本呢?所以我可以 只需在我的位置创建第一个核心数据模型版本 应用程序是 v2 吗?
根据您在此处所说的,该问题似乎与最初的问题不同。您最初的问题是您已经发布了您的应用程序的 v1,但没有明确添加版本化模型。但是,此声明意味着您已对应用程序 v2 的核心数据模型进行了更改,而没有首先创建版本化数据模型。这是完全不同的事情。
如果是这样,那么你的工作就更难了。但是,假设您保留源代码的备份或在 git 之类的存储库中管理代码(我建议所有开发人员都这样做),您可以检索您需要的内容。如果您已经更改了 v2 的核心数据模型,您需要做的是将当前数据模型转换为版本化模型,然后恢复/签出应用程序的 v1 副本,复制核心数据模型(*. xcdatamodel 文件)从那里导入到您当前的项目中,以便您同时拥有 v1 数据模型和较新的数据模型。然后,您可能能够使用轻量级迁移,如上所述。
请注意,这里的关键问题是您何时更改了数据模型。您的应用被称为 v1 还是 v2 基本上与该问题无关,除了很明显可能是您在将应用的版本号更改为 v2 的同时对数据模型进行了更改。
【讨论】:
感谢 Duncan - 请注意,如果我向您澄清“核心数据需要能够在运行时自行找到源和目标托管对象模型” - 我将如何检查我的代码?我真的只是复制/粘贴了标准的苹果代码来重新设置核心数据。我敢肯定这可能没问题,但从学习的角度来看,我有兴趣听到答案...... 所有这意味着在您的应用程序中,您保留了两个托管对象模型......也就是说,您不会对原始模型进行更改,而是按照说明创建一个版本化的设置包括复制现有模型并对其进行更改。然后,您将新模型设置为新模型。当应用程序启动时,它会看到设备上/模拟器中存储的模型与当前模型不匹配。然后它会查看是否有另一个模型,发现有,然后在两者之间应用它可以进行的任何自动迁移。因此“找到……它自己”。 :) 更仔细地阅读您的问题...更明确地澄清:为了促进源模型和目标模型之间的这种连接,您没有在代码中实现任何内容,您不必更改任何访问您的数据存储的代码,就像任何获取的结果控制器等一样。您只需设置一个新模型,Core Data 根据两个模型的存在以及设备上数据存储的状态推断连接本身.如果可以使用轻量级迁移,那简直就像变魔术一样...... 感谢 Duncan - 今天尝试重新开始测试和更新 添加了一个版本并根据developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/… 更新了一些代码,但邓肯似乎不起作用。 Got "developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/…", reason=Can't find model for source store.【参考方案2】:保存您当前的非版本化模型文件(.xcdatamodel 包)。
现在,创建一个新的模型版本。您将拥有一个 .xcdatamodeld 文件,而不是单个 .xcdatamodel 包。在Finder中右键单击它,选择“显示包内容”。这会将其作为目录打开 - 将旧的 .xcdatamodel 文件拖到新版本的 .xcdatamodel 包旁边的目录中。
现在,如果可能,自动迁移应该可以工作,您可能不需要映射模型。测试以确保虽然!!!
我在生产应用程序中使用了这种方法,并且确实有效。只要 CoreData 可以找到应用程序正在使用的当前模型,以及应用程序所依赖的模型的新版本,就可以尝试自动迁移。
【讨论】:
【参考方案3】:是的,因为通过创建新版本,您还可以创建版本映射文件。该文件告诉应用程序哪些键将更改为新版本中的哪些键(当然还有哪些被删除和创建)
苹果文档:http://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/CoreDataVersioning/Articles/vmMappingOverview.html
【讨论】:
所以只是为了确认一下,我不必在 XCode 中将我的核心数据模型回溯到它看起来像 v1 的样子,然后再对其进行版本化?所以我可以在我的应用程序处于 v2 的位置创建第一个核心数据模型版本? 对不起,我不太明白这个问题。您有一个应用程序,已经使用 CoreData 存储,现在想要开始对其进行版本控制。我对吗?是的,即使您之前有更多版本,您也可以从“v1”开始。 (这就是我在我的应用程序中所做的。我第一次真的不需要迁移,所以我总是删除旧的并从空白数据库开始) 可能在没有 v1 版本数据库的情况下使用映射模型,但您需要做的一件事是存储代表当前数据库的唯一 UUID - 每次您对 Core Data 进行更改,它会为该数据库版本生成一个新的唯一 ID。即使只是版本控制而不更改模型也可能会创建一个新版本。要开始创建版本化模型,保留您拥有的内容,然后创建一个新版本并进行更改,然后创建一个映射文件 - 确保来自数据库的唯一 ID 与您当前拥有的相同。 @Kendall - 谢谢,但您是否暗示“自动轻量级迁移”不起作用?即需要创建一个映射模型... 我很确定如果找不到当前版本的模型,自动迁移将无法工作。但是我还有一个想法,我会单独发布......以上是关于如果我已经发布的 v1 没有版本化的 Core Data 模型,我可以使用“自动轻量级迁移”吗?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用opencv获取已经灰度化二值化的一张黑色图片中的一个亮点的具体像素坐标