19

我目前遇到一个问题,即在后台子线程(其父线程是主 UI 线程上下文)上创建一个新对象并保存导致我NSFetchedResultsController显示两个新对象:一个带有临时对象objectID,一个带有永久对象objectID。这似乎是某种错误,除非我遗漏了什么。

所以我想我会为我创建的任何新对象手动获取永久 ID。这修复了重复行问题,但引入了新的随机错误(例如“无法满足对象的错误”,指的是我创建的新对象)。如果有人对前面提到的任何事情发生的原因有任何想法,请分享。

我猜obtainPermanentIDs这是朝着正确方向迈出的一步。但是我什么时候调用这个方法呢?在保存到子上下文之前?在救了孩子之后,在父母之前?在父母之后?目前我的设置是这样的:

masterMOC - private queue tied to the persistent store, so physical saves happen here
----mainMOC - main queue tied to the UI, child of masterMOC
-------backgroundMOC - private queue, child of mainMOC

因此,如果我在 上创建一个新对象backgroundMOC,并且打算立即保存到磁盘(这意味着我必须在所有三个上下文中调用 save:),我应该在哪里调用obtainPermanentIDs

(或者如果有人有不同的解决方案,而不是调用获取永久 ids?这个方法是为了解决什么问题?我为什么要调用这个方法?)

更新: 我想我知道发生了什么(虽然这只是一个理论),但不知道如何解决它。当对象物理保存到磁盘时,Core Data 显然会为对象生成永久 ID。所以在我的情况下,直到我在 masterMOC 上调用 save 才会发生这种情况。目前我在 backgroundMOC 上创建新对象时所做的是:

  1. 保存在 backgroundMOC 上(以便将更改向上推送到 mainMOC 并且我的表格视图可以插入新行)
  2. 保存在 mainMOC 上(以便我可以准备保存到磁盘)
  3. 保存在 masterMOC 上(最终保存到磁盘)

这里发生的情况是,在 backgroundMOC 上调用 save 会触发 UI 更新,并导致获取的结果控制器插入一个仍然只有一个临时 ID 的新对象。但是随后在 masterMOC 上调用 save 会导致所有对象都获得分配的永久 ID,这会导致另一个 UI 更新,为这个“新”对象插入另一行!通过注释掉最后一次 masterMOC 保存,我不再看到重复的条目。我在这里做错了什么,还是这是某种错误?

另一个更新:我想我已经基本确认了这个错误。我在 backgroundMOC 上调用 save ,然后设置一个计时器在 5 秒后在 mainMOC 和 masterMOC 上调用 save 。保存到 backgroundMOC 后,立即在我的表中插入了一个新行。5 秒后(保存 main 和 master),插入另一个新行。(首先插入的行具有临时 ID,最新插入的行具有永久 ID)。

4

1 回答 1

11

我遇到了完全相同的问题,当然,在调试所有内容以发现问题是临时 ID 的特别困难和令人沮丧的一天之后。:)

我和你有完全相同的结构,我也有 NSManagedObjectContext 的子类来编码我期望在后台和主上下文中保存的行为——即,在后台上下文中保存应该保存主上下文(主上下文应该同步任何与外部服务更改的对象,这无关紧要,但值得一提,以解释为什么我有两个子类),并且在主上下文中保存应该保存主上下文。

在我的 RFSImportContext 子类(相当于你的 backgroundMOC)中,我实现- save:调用[super save:],然后调用[self.parentContext performBlock:](这里的 self.parentContext 相当于你的 mainM)C,其中块调用obtainPermanentIDsForObjects:主上下文- updatedObjects- insertedObjects数组的内容,然后我保存主语境。

正如您所描述的,我不再将临时对象泄漏到我的 NSFetchedResultsController 中。稍微改善这种情况的一种方法是使用 RFSMainContext 子类(同样,相当于您的 mainMOC)来实现- save:获取永久对象 ID,保存自身,然后保存主上下文。这规定了我们总是希望主上下文在保存时具有其中对象的永久 ID 的行为。

于 2012-07-24T19:57:14.080 回答