我有一个操作对象,它创建了自己的托管对象上下文。当主线程集中在UI方面时,操作对象基本上执行计算以从主线程中取消负载。此操作对象的MOC在应用程序中共享一个公共持久存储。
有时会发生这样的情况:在执行操作时,主线程的MOC会收到后端更改的通知。因此,我尝试合并MOC的更改,其中可能发生模型对象中的一些删除。在极少数情况下,正如我所观察到的,操作对象可能尚未实现,并且它们处于错误状态,同时主线程将更改存储到MOC(以及持久存储)中。我的应用程序崩溃了。
根据标准文本,我有一个专用的MOC用于我的线程,根据我的理解,应该从线程的MOC访问故障数据。它是否有助于从线程的MOC访问故障请求,例如,同一个对象可能已从商店中删除?
请参阅此堆栈跟踪:
处理此问题的更好方法是什么?
我从这篇文章中了解到:https://stackoverflow.com/a/5722914/260665线程的托管对象上下文不知道商店下面的更改,并且预期商店中存在故障对象。所以,更好的是:
使用NSManagedObjectContextDidSaveNotification
通知(来自:https://stackoverflow.com/a/5722914/260665)
在尝试使用MOC上的NSManagedObject
访问其属性之前,检查商店中是否存在-existingObjectWithID
的记录(来自: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>'
它崩溃了哪条线?
它在任何一个排序描述符中崩溃,其中faluted Managed对象的内部属性试图通过排序描述符访问以进行排序。由于它是一个线程,我们不确定在商店中何时删除了底层对象。因此,线程崩溃有时也会出现在我的统计计算代码中。
为什么要结合两个FRC的结果?
因为,该项目最初开始时针对这两个案例采用了不同的MOC,现在尽管MOC是单一的,但差别仍然存在。但我不认为让离散的FRC具有自己的目的是一个问题。
答案 0 :(得分:1)
做了足够的研究,避免这种情况发生的唯一方法是通过收听通知来更新集合(问题中提到的第一个解决方案),另一种方法是使用-existingObjectWithID
进行双重检查(第二个解决方案) )在访问属性之前。
但在我的情况下,排序描述符在内部访问已删除(来自持久存储)托管对象的属性。让我别无选择,只能处理线程中的异常(第三个解决方案)并忽略该线程的(错误的)结果。
答案 1 :(得分:1)
如果您无法合并或者不想触摸操作MOC - 例如因为它当前正在使用,您需要保证操作和数据更新变成序列化。
这个想法是,当操作运行时,它假定它当前的数据状态视图是常量,因此必须不能被改变。
您有几个选择来保证这一点:
如果某个操作正在运行,并且您收到了更新请求并希望立即更新包括共享持久存储的数据,则需要先取消该操作并等待该操作已执行完成(随后在操作系统的MOC上不会进行访问)。然后开始更新主MOC中的数据。当包含持久存储的更新完成后,您可以使用新初始化的或正确合并的 MOC重新启动操作 - 反映数据的实际状态。
同样,您可以将更新请求推迟到运行操作完成之后。