将子ManagedObjectContext所做的更改推送(保存)到其父级时,实体的重复

Car*_*ter 5 concurrency nested core-data nsmanagedobjectcontext ios

我希望(甚至希望)这将是一个愚蠢的问题,但在与这个问题摔跤了好几个小时后,我需要一些见解.

我的iOS 5.1应用程序使用嵌套的MOC,具有PrivateQueueConcurrency子MOC,称之为MOC-Child,其父级是MainQueueConcurrency MOC,称之为MOC-Parent.MOC-Parent支持显示其实体的表视图.

MOC-Child由解析器使用,该解析器在非主线程上异步运行,以创建与从URL连接解析的XML实体描述相对应的新实体,然后通过以下方式将新实体推送到MOC-Parent.保存在MOC-Child上,它在表格视图中显示它们.这非常有效:

1) Parser creates entity in MOC-Child
2) Parser saves MOC-Child
3) New entity is added to MOC-Parent
4) New entity is displayed in MOC-Parent's table view
Run Code Online (Sandbox Code Playgroud)

但是,此Feed中任何给定实体的描述都可能随时间发生变化,因此需要在应用程序中修改其描述的实体,并更新表视图中的单元格.因此,对于feed中的每个实体描述,解析器尝试获取与所描述的实体具有相同id的MOC-Child中的实体(如果有),并且如果存在,则将现有实体的值与描述值进行比较.看看是否有任何变化.当解析器以这种方式检测到实体已被修改时,它会使用描述中的新值更新MOC-Child中现有实体的值,然后保存MOC-Child以将更改推送到MOC-Parent.

这是出问题的地方.我原以为在MOC-Child中对获取的实体所做的更改,当通过保存推送到父级时,只需"出现"在MOC-Parent中的"相同"实体中.但是,我看到的情况是,MOC-Child中已更改的实体被添加到MOC-Parent,就好像它是一个完全独立的新实体 ; 结果是MOC-Parent以及它驱动的表视图最终为每个修改过的实体提供了两个实体:

1) Parser modifies existing entity in MOC-Child
2) Parser saves MOC-Child
3) Modified entity is _added to_ MOC-Parent
4) Entity is displayed _twice_ in MOC-Parent's table view
Run Code Online (Sandbox Code Playgroud)

是什么赋予了?如果我不能在MOC-Child中进行更改MOC-Parent中现有实体的值,我需要做什么?如果我能够在MOC-Child中这样做,除了保存MOC-Child以便在MOC-Parent中进行更改而不再添加第二次实体之外,我还需要做什么?

提前感谢您提供的任何帮助或见解!

卡尔

PS一些澄清.当我说已将更改的实体添加到MOC-Parent时,我的意思是监视MOC-Parent的NSFetchedResultsController 为更改的实体发出NSFetchedResultsChangeInsert更改类型(不是 NSFetchedResultsChangeUpdate更改类型),即使"相同"实体已经存在于MOC-Parent中.

此外,当我说"相同"实体时,我的意思是MOC-Parent中的实体具有相同的描述提供的id(在本例中为NSString)作为在MOC-child中更改的实体(不一定是相同的objectID) ,实际上显然有一个不同的objectId).

enj*_*yem 1

我想,既然这是一个如此古老的问题,它就不再是一个问题了。但由于我最近发现自己遇到了类似的情况,我想我应该提供我的解决方案。

我将包含数千个对象(与一个或多个条形码关联)的数组下载到一个 XML 文件,然后使用 NSOperation 子类在后台上下文中批量解析并保存该文件。磁盘上下文(连接到持久存储)侦听 NSManagedObjectContextDidSaveNotification,此时它也会保存(请记住在块中执行此操作)。

[self.diskManagedObjectContext performBlockAndWait:^{
    NSError *error;
    if (![self.diskManagedObjectContext save:&error]) {
        NSLog(@"error saving to disk: %@",error);
    }
}];
Run Code Online (Sandbox Code Playgroud)

棘手的部分是,在完全解析 XML 文件并将信息加载到数据库之前,可能会扫描任何这些对象的条形码(在 UI 上下文中)。我有一个由 NSFetchedResultsController 支持的表视图,它显示扫描的对象,这些对象在标题中显示“未知”,直到从后台加载检索数据为止。就像 Carl 的情况一样,这些对象需要在后台上下文保存时更新。

为了解决这个问题,我使用了一个类似于本问题中的三上下文系统,具有 UI 上下文和后台上下文,这两个上下文都是我的主磁盘上下文(与持久存储相关联)的子上下文。因此,在 XML 解析期间,我在后台上下文(也从父磁盘上下文中提取)中对对象的条形码运行查询,以查看是否已使用该条形码创建了对象。如果有,我只需更新信息、重新保存、重置磁盘上下文,然后从 UI 上下文中调用refreshObject:mergeChanges: 即可从磁盘上下文中提取这些更改。这成功刷新了表,而没有创建重复项。

我最初尝试只使用两个上下文,一个背景上下文和一个 UI 上下文,但虽然我从未最终创建重复的对象,但我非常擅长挂起 UI 线程。

我想重要的问题是您如何修改现有实体?并且不要忘记重置。