【问题标题】:What do I have to do to get Core Data to automatically migrate models?我需要做什么才能让 Core Data 自动迁移模型?
【发布时间】:2010-11-04 07:49:58
【问题描述】:

我已阅读有关 Core Data 模型的自动/轻量级迁移的文档 - 但我在实现它时遇到了问题。

据我了解,应用程序应该注意到它拥有的模型和设备上已经存在的模型是不一样的。如果您只添加了属性或关系以及类似的简单更改,则应自动升级模型。

任何指针 - 我需要在 Xcode 中设置一些东西吗?

【问题讨论】:

    标签: core-data


    【解决方案1】:

    我现在发现这很简单——只要你知道去哪里看。

    在我的 AppDelegate 中,我设置了 NSPersistentStoreCoordinator - 您需要为此添加一些选项来告诉它处理自动迁移:

    NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
    
    [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
    
    [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];
    
    NSError *error;
    _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: [self managedObjectModel]];
    
    if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:options error:&error]) {
        // Handle error
        NSLog(@"Problem with PersistentStoreCoordinator: %@",error);
    }
    

    那么你需要在xCode中做一个小技巧:

    1. 选择您的 xcdatamodel 文件
    2. 选择顶部的设计菜单 - 然后选择数据模型 - 然后选择添加模型版本
    3. 然后,您的 xcdatamodel 文件将被移动到与您的 xcdatamodel 文件同名但扩展名为 xcdatamodeld 的新目录中 - 此目录中将有第二个文件,名称中包含 2。选择新文件,然后选择 Design->Data Model->Set Current Version (in Xcode 4 you do this)
    4. 如果您已经进行了导致项目不兼容的更改,请从原始 xcdatamodel 文件中删除这些更改。如果您尚未进行更改 - 只需编辑 2.xcdatamodel 文件(您刚刚制作的当前版本)。
    5. 现在,当您将此版本安装到具有旧型号的设备上时,它会自动将该型号升级到新型号。

    这看起来很棒而且很简单——但我认为在开发过程中更改模型时需要小心——否则你将不得不为每次更改创建一个新版本。

    我认为我将保留所有更改的文件,然后一旦我准备好部署我的更新,我将删除所有中间文件并仅使用最旧和最新的模型进行部署。


    更新(2011 年 7 月 15 日):

    感谢@rockstarberlin 指出苹果有更新的文档:

    Xcode 4: Setting a Managed Object Model’s Current Version

    更新:2013 年 8 月 19 日更好的链接:

    https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/CoreDataVersioning/Articles/vmModelFormat.html

    【讨论】:

    • 我建议阅读核心数据迁移和版本控制指南,可在 Xcode 文档查看器和 developer.apple.com 上找到。
    • 我没有找到简单的答案 - 花了一段时间才知道如何做到这一点。
    • NSInferMappingModelAutomaticallyOption 效果很好,但仅适用于简单的映射,例如更改属性的名称。对于更复杂的事情(关系、删除或添加实体),您需要添加映射模型。如果 Xcode 抱怨 NSInferMappingModelAutomaticallyOption 未声明,请将 #import 添加到您的应用委托头文件中。
    • 我在我的模型中添加了一些实体并得到了臭名昭著的“用于打开商店的模型与用于创建商店的模型不兼容”错误。您的解决方案解决了它!非常感谢!
    • 如果您在按照这些说明操作后遇到“无法将模型与两个不同的命名实体合并”错误,请参阅下面的 Santthosh 答案。
    【解决方案2】:

    这非常有用。苹果的文档——像往常一样——非常不完整。我建议进行干净的构建,因为在进行这些更改后第一次运行时遇到错误“无法将模型与两个不同的实体 xxx 合并”。干净的构建修复了它。

    【讨论】:

    • 一个干净的构建也解决了我的问题。
    【解决方案3】:

    Grouchal 的答案是完美的...但是如果您在多次清理构建后仍然遇到“无法将模型与两个不同的实体 xxx 合并”...您可能对 managedObjectModel 的方式存在问题加载...看看这个...帮助我修复它..

    core data migration problems

    【讨论】:

      【解决方案4】:

      另外,如果您像我一样偶然发现这篇文章,在收到“用于打开商店的模型与用于创建商店的模型不兼容”错误之后,您只是在使用模拟器进行调试并想要完全替换安装的旧模型,您可以重置模拟器应用程序或从模拟器中删除您的应用程序可能也可以。

      直到阅读这里的帖子,我才想到尝试这个,此时我意识到我已经在模拟器中安装了应用程序,然后随后更改了模型,导致上述运行时错误。

      【讨论】:

        【解决方案5】:

        为了跟进 Santthosh 的回答,我想我会在此处发布代码 sn-p。您需要使用 initWithContentsOfURL: 而不是 mergedModelFromBundles: 创建 managedObjectModel 否则您会收到错误:

        无法合并具有两个不同的模型 实体 XXX 和 XXX

        如果您的模型文件被命名为“模型”,那么创建 managedObjectModel 的方法如下:

        NSString *path = [[NSBundle mainBundle] pathForResource:@"Model" ofType:@"momd"];
        NSURL *momURL = [NSURL fileURLWithPath:path];
        managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:momURL]; 
        

        归功于this blog post

        【讨论】:

          【解决方案6】:

          Xcode 4 中的菜单发生了一些变化。这是如何在 Xcode 4 中执行此操作的描述:

          Xcode 4: Setting a Managed Object Model’s Current Version

          【讨论】:

          • 链接已损坏。 Apple 文档的链接持续了大约两个月 :(
          【解决方案7】:

          我多年来一直有这个问题,我尝试了所有这些答案都无济于事。今天我终于弄清楚我做错了什么。非常简单的问题,但我忽略了它。创建数据模型的较新版本时,如果要添加列,请确保将它们标记为 OPTIONAL。如果不这样做,简单的迁移将不起作用,因为不会填写新的列值。

          当我确定我的新列已选中“可选”后,我再次尝试迁移,它成功了。

          【讨论】:

            【解决方案8】:

            由于另一个问题,我偶然发现了这篇文章,但错误是“用于打开商店的模型配置与用于创建商店的模型配置不兼容。” p>

            这是我的问题及其解决方案。在我的模型中,我使用的是配置。我将一些实体存储在一个文件中,而将其他实体存储在第二个文件中。 (我有一些可能需要定期下载的默认值,将它们合并到整体中会非常痛苦)。无论如何,我创建了一个新实体。该程序似乎运行良好,但每当我退出时,我都会收到上述错误。

            解决方案是查看我的配置,意识到我有一个当前不在任何配置中的实体,然后将其添加到其中。像梦一样奔跑。

            这不会解决 OP 的问题。但也许一些通过谷歌登陆这里的沮丧的人会在我所在的船上:)

            【讨论】:

              【解决方案9】:

              iOS 4.0+

              NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"model" withExtension:@"momd"];
              managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
              

              【讨论】:

                【解决方案10】:

                对@Grouchal 上面关于 Xcode 版本 5 的精彩说明进行小幅编辑:

                旧: 2. 选择顶部的设计菜单 - 然后选择数据模型 - 然后选择添加模型版本

                版本 5+: 2. 选择编辑器菜单,然后添加模型版本...,输入您的版本名称和基于模型(从列表中选择您的原始模型)

                【讨论】:

                  猜你喜欢
                  • 2012-07-13
                  • 1970-01-01
                  • 2011-11-13
                  • 2021-05-14
                  • 2017-12-22
                  • 1970-01-01
                  • 2010-10-15
                  • 2019-11-15
                  • 2010-12-31
                  相关资源
                  最近更新 更多