将子项ManagedObjectContext所做的更改复制到实体的父级

我期望(甚至希望)这将是一个愚蠢的问题,但经过这个问题摔跤了好几个小时,我需要一些见解。

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

MOC-Child被parsing器使用,该parsing器在非主线程上asynchronous运行,以创build与从URL连接parsing的XML实体描述对应的新实体,然后将新实体推送到MOC-Parent,通过保存在MOC-Child上,以表格forms显示它们。 这很好用:

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 

但是,此提要中任何给定实体的描述可能会随时间而改变,以便它所描述的实体需要在应用中进行修改,并更新表视图中的单元格。 因此,对于Feed中的每个实体描述,parsing器都会尝试获取MOC-Child中与所描述的实体具有相同ID的实体(如果有的话),如果有人将现有实体的值与描述值进行比较,看看是否有任何改变。 当parsing器以这种方式检测到实体已被修改时,它用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 

是什么赋予了? 如果我不能在MOC-Child内做什么来改变MOC-Parent中现有实体的价值,我需要做些什么? 如果我可以在MOC-Child内部这样做,除了保存MOC-Child以便在MOC-Parent中做出更改而不需要第二次添加实体之外,还需要做什么?

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

卡尔

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

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

我可以想象,因为这是一个古老的问题,这不再是一个问题。 但是最近我发现自己也在类似的情况下摔跤,我想我会提供我的解决scheme。

我将数以千计的对象(通过一个或多个条形码关联)的数组下载到一个XML文件中,然后使用NSOperation子类在后台上下文中分批parsing和保存。 磁盘上下文(连接到持久性存储)侦听NSManagedObjectContextDidSaveNotification,在这一点上它也保存(记得在块中这样做)。

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

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

为了处理这个问题,我使用了一个类似于这个问题的三上下文系统,它有一个UI上下文和后台上下文,这两个都是我的主磁盘上下文(与持久存储相关)的子元素。 因此,在XMLparsing过程中,我在后台上下文中的对象条形码上运行查询(也从父上下文中获取),以查看是否已经使用该条形码创build了对象。 如果有,我只是更新信息,重新保存, 重置磁盘上下文 ,并从UI上下文中调用refreshObject:mergeChanges:从磁盘上下文中提取这些更改。 这成功刷新表,而不会创build重复。

我原本只使用两个上下文,一个后台上下文和一个UI上下文,但是我从来没有结束创build重复的对象,我非常擅长悬挂UI线程。

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