我有一个操作对象,它创建自己的托管对象上下文。操作对象执行计算基本上是为了减轻主线程的负载,而主线程则专注于 UI 方面。此操作对象的 MOC 在整个应用程序中共享一个公共(public)持久存储。
有时会发生这样的情况:在执行操作时,主线程的 MOC 会收到后端更改的通知。因此,我尝试合并 MOC 的更改,其中模型对象中的一些删除可能会发生。据我观察,在某些罕见的情况下,操作对象可能尚未实现,并且它们处于故障状态,同时主线程将更改存储到 MOC(以及持久存储)中。我的应用程序在这种情况下崩溃了。
根据标准文本,我的线程有一个专用的 MOC,并且根据我的理解,应该从线程的 MOC 访问故障数据。当同一对象可能已从存储中删除时,从线程的 MOC 访问错误请求是否会有所不同?
请查看此堆栈跟踪:
处理这个问题更好的方法是什么?
我确实从这篇文章中了解到:https://stackoverflow.com/a/5722914/260665线程的托管对象上下文不知道存储底层的更改,并且错误的对象应该存在于存储中。因此,最好是:
当存储中存在任何基础更改(删除)时,使用
NSManagedObjectContextDidSaveNotification
更新线程中的对象集合。通知(来自:https://stackoverflow.com/a/5722914/260665)检查是否
NSManagedObject
在尝试使用-existingObjectWithID
访问其属性之前,其记录已存在于存储中在 MOC 上(来自:https://stackoverflow.com/a/14297708/260665)处理代码中的异常? (最后的手段,来自:https://stackoverflow.com/a/15361906/260665)
我不可能继续使用解决方案 1 和 2,因为它不是直接访问 NSManagedObject 的属性,我有 NSFetchedResultController,它具有应用程序崩溃的排序描述符:
-(NSMutableArray*)fetchedTaskObjects
{
if (nil==fetchedTaskObjects_ && self.taskLocalFetchedResultsController && self.persistantTaskFetchedResultsController)
{
NSArray *allNonPersistantTasks = [self.taskLocalFetchedResultsController fetchedObjects];
NSArray *allPersistantTasks = [self.persistantTaskFetchedResultsController fetchedObjects];
fetchedTaskObjects_ = [[NSMutableArray alloc] init];
[fetchedTaskObjects_ addObjectsFromArray:allNonPersistantTasks];
[fetchedTaskObjects_ addObjectsFromArray:allPersistantTasks];
NSSortDescriptor *tasksSortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"self.mockTaskCounter"
ascending:YES];
NSSortDescriptor *shortTextSortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"self.shortText"
ascending:YES];
NSSortDescriptor *headerTextSortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"self.accountAssignmentText"
ascending:YES];
[fetchedTaskObjects_ sortUsingDescriptors:[NSArray arrayWithObjects:tasksSortDescriptor, shortTextSortDescriptor, headerTextSortDescriptor, nil]];
}
return fetchedTaskObjects_;
}
那么有什么建议可以以正确的方式找到解决方案吗?
编辑: 我收到的错误(异常):
CoreData could not fulfill a fault for '0x2b0298a0 <x-coredata://E7E91AFC-5BE6-4996-B28F-92CD115A5D0A/CSTaskRegister/p14746>'
哪一行崩溃了?
它会在任何一个排序描述符中崩溃,其中排序描述符尝试访问损坏的托管对象的内部属性以进行排序。由于它是一个线程,我们不确定存储中的底层对象何时被删除。所以,我的统计计算代码有时也会出现线程崩溃的情况。
为什么要合并两个 FRC 的结果?
因为,该项目最初针对这两种情况使用了不同的 MOC,现在虽然 MOC 是单一的,但差异仍然存在。但我不认为拥有具有其自身用途的离散 FRC 是一个问题。
最佳答案
做了足够的研究,避免这种情况发生的唯一方法是通过监听通知来更新集合(问题中提到的第一个解决方案),另一种方法是仔细检查 -existingObjectWithID
(有问题的第二个解决方案)在访问属性之前。
但就我而言,已删除(从持久存储中)托管对象的属性正在由排序描述符在内部访问。让我别无选择,只能处理线程中的异常(有问题的第三个解决方案)并忽略该线程的(错误)结果。
关于iphone - 独立 ManagedObjectContext 中的 Coredata 对象故障与持久存储中的更改,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18828164/