我需要做什么才能使Core Data自动迁移模型?


96

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

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

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

Answers:


138

现在,我发现这很简单-一旦您知道要看的地方。

在我的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。选择新文件,然后选择“设计”->“数据模型”->“设置当前版本”(在Xcode 4中,您可以执行此操作
  4. 如果您已经进行了导致项目不兼容的更改,请从原始xcdatamodel文件中删除这些更改。如果您尚未进行更改-只需编辑2.xcdatamodel文件(您刚制作了当前版本的文件)即可。
  5. 现在,当您将此版本安装到具有旧型号的设备上时,它将自动将该型号升级到新型号。

这似乎很简单,就像我想要的那样简单-但我认为在更改模型时需要在开发过程中小心-否则,每次更改都必须创建一个新版本。

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


更新(15/07/2011):

感谢@ rockstarberlin指出apple上有更新的文档:

Xcode 4:设置托管对象模型的当前版本

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

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


我建议阅读Xcode doc查看器和developer.apple.com上的《核心数据迁移和版本控制指南》。
猎人

1
我没有在那里找到简单的答案-花了一段时间才知道如何做到这一点。
Grouchal

NSInferMappingModelAutomaticallyOption可以很好地工作,但仅适用于简单的映射,例如更改属性名称。对于更复杂的事情(关系,删除或添加实体),您将需要添加映射模型。如果Xcode抱怨未声明NSInferMappingModelAutomaticallyOption,则将#import <CoreData / CoreData.h>添加到您的应用程序委托头文件中。
Elise van Looij 09年

我在模型中添加了一些实体,并得到了臭名昭著的“用于打开商店的模型与用于创建商店的模型不兼容”错误。您的解决方案已解决!非常感谢你!
卡斯滕·西尔兹

1
如果遵循这些说明后出现“无法合并具有两个不同名称的实体的模型”错误,请参见下面的Santthosh答案。
benvolioT 2010年

14

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


干净的构建也解决了我的问题。
jrainbow

6

Grouchal的答案是完美的...但是,即使清理了几次构建后,如果仍然仍然存在“无法将模型与两个不同的实体xxx合并”的情况,则可能是托管对象模型的加载方式存在问题。 。看看这个...帮助我修复了它。

核心数据迁移问题


3

另外,如果您像我一样偶然发现了此帖子,则在收到“用于打开商店的模型与用于创建商店的模型不兼容”错误后,您只是在使用模拟器进行调试,并希望完全替换如果安装的是旧型号,则只需重置模拟器应用程序,或者从模拟器中删除您的应用程序也可能会起作用。

直到阅读了这里的文章,我才尝试尝试此操作,这时我意识到我已经在模拟器中安装了该应用程序,然后更改了模型,从而导致了上述运行时错误。


1

为了跟上Santthosh的回答,我想我应该在这里张贴代码片段。您需要使用创建您的ManagedObjectModel initWithContentsOfURL:mergedModelFromBundles:否则您将得到错误:

无法将模型与两个不同的实体XXX和XXX合并

如果您的模型文件名为“模型”,请按照以下方法创建managedObjectModel:

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

归功于此博客文章



1

我遇到这个问题已有多年了,而我尝试了所有这些答案都无济于事。今天,我终于弄清楚自己在做什么错。非常简单的问题,但我忽略了它。创建新版本的数据模型时,如果要添加列,请确保将其标记为可选。如果您不这样做,那么将无法进行简单迁移,因为将不会填写新的列值。

一旦确定我的新列已选中“可选”,我就再次尝试了迁移并成功了。


1

由于出现其他问题,我偶然发现了该帖子,但错误是“ 用于打开商店的模型配置与用于创建商店的模型配置不兼容。

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

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

这不会解决OP的问题。但是也许有些沮丧的人通过谷歌降落在这里,我会在船上:)


0

iOS 4.0以上

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

0

对上面Xcode版本5的@Grouchal很棒的说明进行较小的编辑:

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

版本5+:2.选择“编辑器”菜单,然后选择“添加模型版本…”,键入您的版本名称,然后根据模型(从列表中选择原始模型)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.