在新版本中添加现有实体的新属性时核心数据崩溃

Posted

技术标签:

【中文标题】在新版本中添加现有实体的新属性时核心数据崩溃【英文标题】:Core Data crash when adding new Attribute of existing Entity in a new version 【发布时间】:2017-02-14 14:47:24 【问题描述】:

我的应用程序中有一个使用 UIManagedDocument 的核心数据数据库,并在旧版本之上添加了一个新版本。

如果我在不更改旧实体的情况下添加新实体,则新版本没有问题。但是一旦我向旧版本的现有实体添加了新属性。 UIManagedDocument 在调用 initWithFileURL 时崩溃。下面是我创建 UIManagedDocument 的方法。

UIManagedDocument *document = [[UIManagedDocument alloc] initWithFileURL:databaseURL];
self.databaseDocument = document;


NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
                         [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
                         [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];
self.databaseDocument.persistentStoreOptions = options;

似乎它在 initWithFileURL 时调用的 modelByMergingModels 崩溃了

我知道这是由于异常断点而崩溃的代码行。

如果我删除了新添加的属性,请再次创建 NSManagedObject。代码再次运行没有问题。

任何提示为什么它会失败?任何想法将不胜感激。

【问题讨论】:

您是创建了新版本的模型文件,还是直接编辑了模型文件? @TomHarrington 我添加了一个新版本的模型。请看我上传的另一张截图。 【参考方案1】:

它正在崩溃,因为当它尝试创建文档时,尚未设置选项。仅使用init 创建文档,设置其persistentStoreOptions 然后调用configurePersistentStoreCoordinatorForURL:ofType:modelConfiguration:storeOptions:error:

【讨论】:

嗨乔恩,谢谢你的想法。很好的尝试,这是有道理的。但 UIManagedDocument 不能仅使用 init 创建。结果是由于 *** Assertion failure in -[UIManagedDocument init], /BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKit/UIKit-3512.60.12/UIDocument.m:296 是的,你是对的。我再次阅读了UIManagedDocument 文档,现在我明白该类被设计为子类化。尝试创建UIManagedDocument 的子类并实现persistentStoreOptions 以返回您需要的迁移选项。 仍然会因覆盖persistentOptions而崩溃。但是,覆盖 managedObjectModel 使它工作!虽然我不明白为什么,但它有效!【参考方案2】:

从这个问题接受的答案解决了这个问题。 UIManagedDocument migrate data model

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

      return managedObjectModel;

我真的不知道为什么要告诉它 NSManagedObjectModel 的文件名。但是在它崩溃的时候查看堆栈: 它真的在 UIManagedDocument 的 initWithFileURL 调用 managedObjectModel 时崩溃了。在堆栈的更深处,它似乎正在尝试合并 Bundle 中存在的所有模型。也许,我猜这两个版本的模型被视为两个模型合并为一个,而不是两个版本 - 因为这两个版本似乎是 Bundle 中的两个单独文件。在尝试合并时,两个名称相同但属性不同的表的存在导致冲突,这就是它崩溃的原因。

【讨论】:

以上是关于在新版本中添加现有实体的新属性时核心数据崩溃的主要内容,如果未能解决你的问题,请参考以下文章

核心数据:如何处理新版本?

向核心数据实体添加瞬态属性是不是需要新版本模型?

更新了核心数据模型,没有新版本,如何修复?

我没有在新版本中迁移NSPersistentStore,我可以通过应用更新进行恢复吗?

迁移复杂的核心数据模型

使用 Core Data 轻量级迁移和 UIManagedDocument 的“找不到源存储模型”