我目前遇到的问题是在后台子线程(其父级是主UI线程上下文)上创建新对象并保存导致我的NSFetchedResultsController
显示两个新对象:一个带有临时{ {1}},以及永久objectID
。这似乎是某种错误,除非我遗漏了什么。
所以我想我会为我创建的任何新对象手动获取永久ID。这修复了重复的行问题,但引入了新的随机错误(例如“无法实现对象的错误”,引用我创建的新对象)。如果有人对前面提到的任何事情有任何想法,请分享。
我猜objectID
是朝着正确方向迈出的一步。但是我什么时候打电话给这个方法?在保存到子环境之前?保存孩子之后和父母之前?父母之后?
目前我的设置是:
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
上创建一个新对象,并且我打算立即保存到磁盘(这意味着我将不得不在所有三个上下文中调用save),我应该在哪里调用{{1 }}?
(或者,除了调用获取永久ID之外,还有其他解决方案吗?此方法引入了什么问题才能解决?为什么我要调用此方法?)
更新 我想我知道发生了什么(虽然这只是一个理论),但不是如何解决它。当数据物理保存到磁盘时,Core Data显然会为对象生成永久ID。所以在我的情况下,直到我在masterMOC上调用save才会发生这种情况。目前我在backgroundMOC上创建新对象时所做的是:
这里发生的事情是在backgroundMOC上调用save会触发UI更新,并导致获取的结果控制器插入一个仍然只有临时ID的新对象。但是然后在masterMOC上调用save会导致所有对象被分配永久ID,这会导致另一个UI更新,为这个“新”对象插入另一行!通过注释掉最后一个masterMOC保存,我不再看到重复的条目。我在这里做错了什么,或者这是某种错误?
另一个更新:我想我已经证实了这个错误。我在backgroundMOC上调用save,然后设置一个计时器,在5秒后调用mainMOC和masterMOC上的save。 Immediatley保存到backgroundMOC后,会在我的表中插入一个新行。 5秒后(保存main和master时),插入另一个新行。 (首先插入的行具有临时ID,最新的插入具有永久ID)。
答案 0 :(得分:11)
我有完全相同的问题,当然是在一个特别困难和令人沮丧的一天调试一切后发现问题是临时ID。 :)
我有与你完全相同的结构,我也有NSManagedObjectContext的子类来编码我期望在后台和主要上下文中保存的行为 - 即,在后台上下文中的保存应该保存主上下文(和主上下文应该同步任何使用外部服务更改的对象,这是无关紧要但值得一提的解释为什么我有两个子类),并且在主上下文中保存应该保存主上下文。
在我的RFSImportContext子类中(相当于你的backgroundMOC),我实现- save:
来调用[super save:]
,然后调用[self.parentContext performBlock:]
(self.parentContext这里等同于你的mainM)C,其中该块使用主要上下文的obtainPermanentIDsForObjects:
和- updatedObjects
数组的内容调用- insertedObjects
,然后保存主上下文。
我不再像你描述的那样将临时对象泄漏到我的NSFetchedResultsController中。一种改善这种情况的方法是使用RFSMainContext子类(再次,相当于你的mainMOC)来实现- save:
来获取永久对象ID,保存自己,然后保存主上下文。这标准化了我们总是希望主要上下文在保存时对其中的对象具有永久ID的行为。