【问题标题】:Importing old CoreData model into new project将旧 CoreData 模型导入新项目
【发布时间】:2012-04-02 14:06:22
【问题描述】:

我有一个旧的 Xcode 项目,其中包含一个 CoreData 模型(包含模型的版本 1 和版本 2)。出于多种原因,我需要创建一个新的 Xcode 项目并将所有代码转移到新项目中。

我如何导入/传输我的旧 CoreData 模型,以使这个新的二进制文件仍然能够读取并可能迁移我现有用户的 iPhone 和 iPad 上的现有 CoreData 存储。 ?我担心如果我使用这个新项目推送一个新版本,我的用户会将他们的应用更新到最新版本,然后它会因为型号或型号版本号不匹配而崩溃。

我说的不是在同一个应用程序中向数据模型添加新版本。我理解那个过程。这是关于将现有数据模型从旧项目移动/导入/等到新项目中。

我应该只是将文件复制过来并手动将它们添加到我的项目中吗?我是否需要更改构建设置中的内容以解决此问题?

【问题讨论】:

    标签: ios xcode core-data


    【解决方案1】:

    我找到了一个更简单的方法。我用核心数据创建了一个新项目,然后在没有构建或运行它的情况下关闭它。然后我使用 IDE 打开 xcdatamodeld。文本编辑器可能也可以工作。我不得不深入研究内容。这可能是因为我正在使用 PHPStorm,并且它正试图从中创建一个项目。我要编辑的文件如下所示:

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0"   lastSavedToolsVersion="1" systemVersion="11A491" minimumToolsVersion="Automatic"   sourceLanguage="Swift" userDefinedModelVersionIdentifier="">
    </model>
    

    然后我打开源 xcdatamoleld 并将模型标签之间的所有内容复制到新文件中。我关闭了文件并构建了项目。我没有复制实际的模型数据(.storedata)。

    一个警告:在我的原始项目中,我不断地更改模型并删除模型数据。 Xcode 无法处理它并抛出了各种错误。上次我这样做时,我收到了警告:

    CoreData: warning: Unable to load class named 'Performance' for entity 'Performance'.  Class not found, using default NSManagedObject instead.
    

    此警告在新项目中再次出现,因此模型定义中有问题。幸运的是,它不会对执行造成任何问题。如果你没有这个警告,你可能会没事。

    这是 Xcode 8.2.1 的版本,它是一个 Swift 项目。

    【讨论】:

    • 编辑文件的内部是引入恶魔和搞砸你的项目的可靠方法。让 Xcode 为您控制这些东西是个不错的主意,尤其是因为它们可能会因版本而异。
    • OP 询问是否将现有模型导入新项目。没有什么可以“搞砸”的。即使它不起作用,也只需删除新项目并创建另一个。我有第二个项目,它的发展很远。我不会用这种方法。如果 Apple 会提供导入现有模型的方法,我们就不需要这篇文章了。
    【解决方案2】:

    最后,我是这样解决的:

    1. 使用 CoreData 创建新项目
    2. 将原始 CoreData 模型文件复制到我的新项目中。将其添加到项目中。
    3. 删除新项目自动创建的空 CoreData 模型。
    4. 在项目设置的构建阶段、编译源下,我添加了复制的 CoreData 模型文件。

    然后我使用了 Scott 上面提供的代码:

    [NSManagedObjectModel mergedModelFromBundles:nil]
    

    它会自动找到所有模型并将它们组合起来。通过删除自动生成的并添加我转移的,然后一切正常。

    【讨论】:

    • 嗨,所以只需通过 [NSManagedObjectModel mergeModelFromBundles:nil] 加载对象模型,我应该能够检索现有数据吗?我正在尝试查询一个表,但它返回 0 并且 sqlite DB 似乎是空的。 Scott 指出了其他代码 - > [[NSManagedObjectModel alloc] initWithContentsOfURL:[NSURL fileURLWithPath:modelPath]]。
    • Xcode 8:我只需要从另一个项目中提取模型。步骤 1-4 非常适合我!
    • @leanne,所以为了初始化核心数据和对象模型,您是否保留了 Xcode 在创建新项目时提供的代码?
    • 是的,@EdoardoMoreni:是的。不过,我的替换模型文件与 Xcode 创建的模型文件同名。如果您的模型文件名不同,您必须更新代码和设置以显示正确的模型文件名。
    【解决方案3】:

    只要您保持相同的应用程序标识符,您的新代码将替换已安装用户的二进制文件,同时保持其所有数据不变。所以你的新项目本质上是作为一个新的二进制文件交换的。之后,由您确保加载正确的 .sqlite 文件、处理升级等。

    让我进一步编辑一下。 Downvote 很伤心。

    有一个 ZMETADATA 表(或等效表,现在无法访问),其中包含识别事物所需的所有信息。此外,还有散列可以知道当前版本是否存在,以便可以发生自动迁移。如果哈希值存在,并且您已经通过 [[NSManagedObjectModel alloc] initWithContentsOfURL:[NSURL fileURLWithPath:modelPath]] 而不是 [NSManagedObjectModel mergedModelFromBundles:nil] 加载了模型,那么一切都应该很好。

    【讨论】:

    • 我不是在问如何覆盖我的应用程序二进制文件。当新的二进制文件启动并开始读取现有的应用程序存储时,自动迁移需要数据存储和数据模型匹配。如果它们不匹配,CoreData 代码将抛出异常,应用程序将崩溃。
    • 是的……如果您在基于相同的应用程序标识符的应用程序中具有相同的 .xcdatamodeld 的 Core Data 版本,将为您进行迁移。只需将它们添加到您当前的项目中就足够了,是的。
    • 我不清楚哪个代码应该工作。我正在尝试使用@KennyWyland 建议的[NSManagedObjectModel mergeModelFromBundles:nil] 加载对象模型,但它不起作用。我也尝试过 [[NSManagedObjectModel alloc] initWithContentsOfURL:[NSURL fileURLWithPath:modelPath]],但一切都失败了。
    猜你喜欢
    • 1970-01-01
    • 2011-01-02
    • 2016-12-16
    • 1970-01-01
    • 1970-01-01
    • 2018-04-19
    • 2011-04-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多