我开发了一款应用iCollege,现在我想让应用更好。
测试时我想从备份中恢复数据。在启动iCollege时,应用程序崩溃,因为它无法通过Core Data进行版本控制。我现在的问题是,是否可以手动版本化核心数据文件,即遍历现有文件的每个受管对象并使对象适合活动的模型版本。
这样的事情可能吗?
编辑:非常感谢您快速详细的回答。我想我解释的问题并不是很好。这是我的问题的另一种描述
我有一个使用Core Data创建的文件,其中有一些实体Course
和Teacher
的对象。我用这个文件替换我的应用程序的核心数据文件。当我下次想要调用一个方法时启动应用程序,该方法使用Course
和Teacher
的对象读取文件的托管对象,并将其转换为实体,例如Subject
和Professor
。属性也可能会改变。我的问题是,如果我可以这样做,即我可以自己修改Core Data文件吗?
我希望我的问题现在可以检查。 : - )
答案 0 :(得分:32)
理论上,您可以手动迁移数据,但这可能不值得。您想使用automatic lightweight migration
。
要执行自动轻量级迁移,您需要设置两个数据模型,然后在代码中告知Core Data执行迁移。这意味着在您阅读完之前不应修改您的数据模型。如果您有(自动或手动)恢复旧模型。你需要它来进行迁移。以下是自动轻量级迁移的工作原理:
首先,您需要为数据模型添加模型版本。选择现有模型,然后从Editor
菜单中添加一个版本:
系统将提示您为数据模型命名,并选择基于该模型的现有模型。
现在,继续对新模型进行更改。完成后,您需要告诉Core Data将此新模型用作当前版本。我们还没有达到代码,所以这部分很简单。 (代码也很简单。)在右侧面板上,选择活动模型,如下所示:
确保在左侧导航器中选择了您的模型,否则您可能看不到右侧的选项。你应该得到这样的东西:
(我实际上在这里使用版本2而不是版本3,但想法是一样的。)
现在,您需要快速更改代码,以便Core Data知道为您执行迁移。
在您的app delegate中的persistentStoreCoordinator
方法内,更改以下行:
if (![__persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error]){
到以下内容(在if
语句之前的行中添加):
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption, [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];
if (![__persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error]){
您实际上已经向Core Data传递了一个选项字典,告诉它为您迁移数据存储。 (仔细看看前面的代码,经过几次阅读后它会有意义。)
编辑你可能会做你想做的事。如果我理解正确,您应该创建一个新的模型版本,执行轻量级迁移,然后手动进行所需的更改。我的上述答案仍然有效,除了您之后想要进行一些手动更改。
答案 1 :(得分:5)
您可以按照以下方式执行此操作。核心数据允许您向NSPersistentStoreCoordinator
添加多个持久存储,因此您需要与协调器关联的两个存储。请注意,不可能使用两个不同的托管对象模型(MOM),您的所有商店只能有一个MOM。
虽然这可能看起来相当困难,但考虑到Core Data也允许使用配置,它相当简单。配置具有名称和关联的实体集。这些集可以重叠 - 也就是说,给定实体可以出现在多个配置中。请参阅相关的documentation
您现在可以通过在不同的商店中拥有不同的实体来轻松处理您的问题, 创建一个模型,它将成为你要去的所有实体的超集 处理(或至少是联合)并定义您需要的子集作为配置。然后,为每个单独的商店指定关联的配置。
像(只是一个示例代码段):
NSPersistentStoreCoordinator *coordinator = [[NSPersistentStoreCoordinator alloc] init];
[coordinator addPersistentStoreWithType:type configuration:@"CourseAndTeacher" URL:aURL options:nil error:NULL];
[coordinator addPersistentStoreWithType:type configuration:@"SubjectAndProfessor" URL:anotherURL options:nil error:NULL];
NSManagedObjectContext *context = [[NSManageObjectContext alloc] init];
[context setPersistentStoreCoordinator:coordinator];