当返回的对象也可能从持久存储中删除时,如何处理 fetchedResultsController 返回的故障对象

Posted

技术标签:

【中文标题】当返回的对象也可能从持久存储中删除时,如何处理 fetchedResultsController 返回的故障对象【英文标题】:How to deal with faulted objects returned by fetchedResultsController when the returned object may also be deleted from the persistent store 【发布时间】:2011-07-14 08:14:57 【问题描述】:
    在我的简单实验中,fetchedResultsController 似乎没有返回错误对象。 fetchedResultsController 是否有可能为特定的索引路径返回错误的 Core Data 对象? 下面的示例代码在主线程上运行。假设在“A 点”,后台线程删除并保存到持久存储区,该对象刚刚由获取的结果控制器返回。现在,当我们尝试访问 dataObject 上的属性时,我们会崩溃,因为由于数据已从持久存储中删除,因此无法完成故障。 我看到的一件事是关系更容易出错。因此,在“A 点”,可以说父对象已从持久存储中删除。然后,当尝试访问父级上的 name 属性时,将发生错误,因为无法完成故障。 防止此类问题的最佳方法是什么?

示例代码:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
    UITableViewCell *cell = code_for_cell_reuse_here;

    PersonModelObject *dataObject = (PersonModelObject *)[self.fetchedResultsController objectAtIndexPath:indexPath];

        /* Point A */

    cell.textLabel.text = dataObject.name;
    cell.detailTextLabel.text = dataObject.parent.name;

    return cell; 

【问题讨论】:

【参考方案1】:

您需要注意来自其他线程的 NSManagedObjectContextDidSaveNotification 并刷新您的上下文。

这可以同步完成,通过使用 performSelectorOnMainThread 或使用块阻塞主线程更新来避免竞争条件。

然后您可以手动或使用 refreshFromContextDidSaveNotification:mergeChanges: 更新本地托管对象上下文,但如果数据量足够大,最简单的方法是在托管对象上下文上调用 -reset 并在获取的结果控制器。

【讨论】:

如果正确处理 NSManagedObjectContextDidSaveNotification 是否保证 NSFetchedResultsController 返回的对象不会出错? 否,保证获取的结果控制器不会返回错误的唯一方法是将 -returnsObjectsAsFaults 设置为 NO。正如下面所述的另一个答案,您还可以使用 relationshipKeyPathsForPrefetching 来指示应该获取某些关系而不是错误的。【参考方案2】:

要回答您问题的另一个方面(希望更有用),NSFetchedResultsController 应该返回故障对象(即已加载的属性),并且您可以使用 NSFetchRequest.relationshipKeyPathsForPrefetching 来预故障关系。

【讨论】:

【参考方案3】:

-[NSManagedObject isDeleted]

【讨论】:

即使有这个检查,竞争条件仍然存在。特别是在 isDeleted 检查之后和访问错误属性之前删除 dataObject 时。 是的。您可以使用锁,或更改为不同的存储/上下文配置。在 ios 5 和 Lion 中,您可以为此使用嵌套上下文。

以上是关于当返回的对象也可能从持久存储中删除时,如何处理 fetchedResultsController 返回的故障对象的主要内容,如果未能解决你的问题,请参考以下文章

从 API 接收时如何处理 blob 存储 url

如何处理已发布的持久卷?

如何处理将 DBNull 传递给函数?

MySQL从入门到精通50讲-MySQL中null值如何处理

Vim:在寄存器中存储多个命令时如何处理换行符?

如何处理进行中的请求以使用redux saga显示加载程序?