核心数据:从NSOperation中删除导致'NSObjectInaccessibleException'并引用已删除的对象

时间:2012-05-20 19:59:15

标签: core-data concurrency nsmanagedobject nsmanagedobjectcontext nsoperation

我的应用程序有NSOperation个子类,用于获取和操作托管对象。我的应用程序还定期清除数据库中的行,这可能导致以下竞争条件:

  • 后台操作获取一堆对象(来自特定于线程的上下文)。它将迭代这些对象并对其属性执行某些操作。
  • 在主要管理对象上下文中删除了一堆行。
  • 后台操作访问从主上下文中删除的对象的属性。这会产生'NSObjectInaccessibleException', reason: 'CoreData could not fulfill a fault'

理想情况下,NSOperation提取的对象可以在上操作,即使在主上下文中删除了。我能想到的最好的方法是:

  • 调用[request setReturnsObjectsAsFaults:NO]以确保Core Data不会尝试解决主上下文中不再存在的对象的错误。这里的问题是我可能需要访问对象的关系,(据我的理解)仍然会出现故障。
  • 预先迭代托管对象,并将我需要的属性复制到单独的非托管对象中。这里的问题是(我认为)我将需要同步/锁定此部分,以防在完成复制之前在主上下文中删除对象。

我错过了一些明显的东西吗?看起来我想要完成的事情似乎与众不同。谢谢你的帮助。

3 个答案:

答案 0 :(得分:0)

你说每个线程都有自己的上下文。这很好。但是,他们还需要保持彼此同步的变化(如何取决于他们的层次结构)。

是全部分配给同一个持久性商店协调员,还是他们有父/子关系?

兄弟姐妹应该监视来自其他兄弟姐妹的NSManagedObjectContextObjectsDidChangeNotification。当子环境保存时,父母将自动收到通知。

答案 1 :(得分:0)

我最终通过在同一队列上执行提取和删除来缓解此问题。

答案 2 :(得分:0)

很好的问题,我只能提供部分答案,并且也非常想知道这一点。不幸的是,你自己的解决方案更多的是解决方法,但不是真正的答案。如果后台操作很长并且你不能在主线程上运行它会怎么样?

我可以说的一件事是你不必调用[request setReturnsObjectsAsFaults:NO],因为获取请求会将数据加载到行缓存中,并且当其中一个错误触发时不会返回数据库。获取的对象(请参阅NSFetchRequest的Apples文档)。但这对关系没有帮助。

我尝试了以下内容:

  1. NSManagedObjectContextWillSave通知中,等待当前后台任务完成并阻止新任务从

    开始
    -(void)contextWillSave:(NSNotification *)notification {
        dispatch_sync(self.backgroundQueue, ^{
            self.suspendBackgroundOperation = YES;
        });
    }
    
  2. NSManagedObjectContextDidSave通知上取消设置suspendBackgroundOperation

  3. 然而,dispatch_sync调用引入了可能的死锁,因此这也不起作用(参见my related question)。此外,它仍将阻止主线程,直到可能冗长的后台操作完成。