我希望(甚至希望)这将是一个愚蠢的问题,但在与这个问题摔跤了好几个小时后,我需要一些见解。
我的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
但是,此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
是什么给出的?如果我不能在MOC-Child中进行更改MOC-Parent中现有实体的值,我需要做什么?如果我能够在MOC-Child中这样做,除了保存MOC-Child以便在MOC-Parent中进行更改而不再添加第二次实体之外,我还需要做什么呢? / p>
提前感谢您提供的任何帮助或见解!
卡尔
P.S。几个澄清。当我说已将更改的实体添加到MOC-Parent时,我的意思是监视MOC-Parent的NSFetchedResultsController为更改的实体发出NSFetchedResultsChangeInsert更改类型( not NSFetchedResultsChangeUpdate更改类型) ,即使"相同"实体已经存在于MOC-Parent中。
另外,当我说"相同"实体,我的意思是MOC-Parent中的实体具有相同的描述提供的id(在本例中为NSString)作为在MOC-child中更改的实体(不一定是相同的objectID,实际上显然具有不同的objectId )。
答案 0 :(得分:1)
我会想象,因为这是一个古老的问题,它不再是一个问题。但是,由于我最近发现自己在类似的情况下摔跤,我想我会提供我的解决方案。
我将数千个对象(由一个或多个条形码关联)的数组下载到XML文件中,然后使用NSOperation子类将其解析并分批保存在背景上下文中。磁盘上下文(连接到持久性存储)侦听NSManagedObjectContextDidSaveNotification,此时它也会保存(请记住在块中执行此操作)。
[self.diskManagedObjectContext performBlockAndWait:^{
NSError *error;
if (![self.diskManagedObjectContext save:&error]) {
NSLog(@"error saving to disk: %@",error);
}
}];
棘手的部分是,在完全解析XML文件并将信息加载到数据库之前,可能会扫描这些对象的条形码(在UI上下文中)。我有一个由NSFetchedResultsController支持的表视图,它显示扫描的对象,在其标题中显示“未知”,直到从后台加载中检索数据。与Carl的情况一样,这些对象需要在背景上下文保存时进行更新。
为了解决这个问题,我使用了一个类似于this question中的三个上下文系统,带有UI上下文和后台上下文,两者都是我主磁盘上下文的子项(与持久性有关)商店)。因此,在XML解析期间,我在后台上下文(也从父磁盘上下文中提取)中对对象的条形码运行查询,以查看是否已使用该条形码创建了对象。如果有,我只是更新信息,重新保存,重置磁盘上下文,并从UI上下文调用refreshObject:mergeChanges:从磁盘上下文中提取这些更改。这会成功刷新表而不会创建重复项。
我最初只使用两个上下文,一个后台上下文和一个UI上下文来尝试这个,但是当我从未创建过重复的对象时,我非常擅长挂起UI线程。
我想重要的问题是你如何修改现有的实体?并且不要忘记重置。