当返回的对象也可能从持久存储中删除时,如何处理 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 返回的故障对象的主要内容,如果未能解决你的问题,请参考以下文章