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

我已经阅读了关于核心数据模型自动/轻量级迁移的文档,但是在实现它的实际中遇到了问题。

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

任何指针 – 我需要在xCode中设置的东西吗?

我现在发现这很简单 – 一旦你知道在哪里看。

在我的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. select你的xcdatamodel文件
  2. select顶部的devise菜单 – 然后select数据模型 – 然后select添加模型版本
  3. 然后,你的xcdatamodel文件将被移动到一个与你的xcdatamodel文件同名的新目录中,但扩展名是xcdatamodeld – 在这个目录中将会有第二个文件名,里面有一个2。 select新的文件,然后devise – >数据模型 – >设置当前版本( 在Xcode 4中,你这样做 )
  4. 如果您已经进行了导致您的项目不兼容的更改,请将这些更改从原始xcdatamodel文件中取出。 如果您还没有进行更改,那么只需编辑2.xcdatamodel文件(您刚制作的最新版本)即可。
  5. 现在,当您将此版本安装到具有旧型号的设备上时,会自动将该型号升级到新型号。

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

我想我会做的是我将保留所有更改的文件,然后一旦准备好部署我的更新,我将删除所有的中间文件,并部署最旧的和最新的模型。


UPDATE(15/07/2011):

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

Xcode 4:设置一个托pipe对象模型的当前版本

更新:8/19/2013更好的链接:

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

这非常有帮助。 苹果的文档像往常一样糟糕地不完整。 我build议做一个干净的构build,因为我遇到了一个错误“无法合并模型与两个不同的实体xxx”当我第一次跑这些变化后。 干净的build设固定起来。

Grouchal的答案是完美的…但是,如果你仍然有“无法与两个不同的实体xxx模型”合并,甚至清理了几次构build…你可能有问题,如何加载managedObjectModel ..看看这个…帮我修好了

核心数据迁移问题

另外,如果你偶然发现这个post,就像我做的那样,在获得“用于打开商店的模型与用于创build商店的模型不兼容”错误之后,您只是使用模拟器进行debugging,并且希望完全replace旧模型安装,你可以重置模拟器应用程序或从模拟器删除您的应用程序也可能工作。

直到阅读这篇文章之前,我都没有想到这一点,在这一点上,我意识到我已经在模拟器中安装了应用程序,然后改变模型,导致上述运行时错误。

为了跟进Santthosh的回答,我想在这里发布代码片段。 你需要用initWithContentsOfURL:创build你的managedObjectModel initWithContentsOfURL:而不是mergedModelFromBundles:否则你会得到错误:

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

如果你的Model文件被命名为“Model”,那么你可以创buildmanagedObjectModel:

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

感谢这篇博文 。

Xcode 4中的菜单发生了一些变化。 这里有一个描述如何在Xcode 4中做到这一点:

Xcode 4:设置一个托pipe对象模型的当前版本

我已经有这个问题多年了,我尝试了所有这些答案无济于事。 今天我终于明白我在做什么错了。 非常简单的问题,但我忽略了它。 创build数据模型的更新版本时,如果您正在添加列,请确保将其标记为可选。 如果你不这样做,简单的迁移将不会工作,因为新的列值不会被填入。

只要我确定我的新列有“可选”选中,我再次尝试迁移,它的工作。

由于不同的问题,我偶然发现了这个post,但错误是“ 用于打开商店的模型configuration与用于创build商店的模型configuration不兼容 ”。

这是我的问题和解决scheme。 在我的模型中,我使用的是configuration 。 我有一些实体存储在一个文件中,其他实体存储在另一个文件中。 (我有一些默认情况,可能会定期需要下载,这将是一个令人难以置信的痛苦合并到整体)。 无论如何,我做了一个新的实体。 该程序似乎运行良好,但每当我退出,我得到了上述错误。

解决scheme是看我的configuration,意识到我有一个当前不在任何configuration的实体,并将其添加到一个。 像梦一样运行。

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

iOS 4.0+

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

小编辑到@ Grouchal真棒指令上面的Xcode版本5:

旧的:2.select顶部的devise菜单 – 然后select数据模型 – 然后select添加模型版本

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