Multithreading iOS 9核心数据线程
我在iOS 9中遇到了iOS 8中没有的核心数据问题 我有一个包含多个Multithreading iOS 9核心数据线程,multithreading,core-data,ios9,Multithreading,Core Data,Ios9,我在iOS 9中遇到了iOS 8中没有的核心数据问题 我有一个包含多个NSManagedObjectContext对象的环境。父级context为并发类型NSMainQueueConcurrencyType,所有视图控制器都有自己的子级context对象。我之所以使用这种系统,是因为我希望有更多独立的上下文,并且只有在我决定应该这样做时才合并它们。子上下文位于专用队列上,因为它在后线程上执行其工作,然后在主线程上的父上下文将更改传播到DB,并在主线程上执行其需要的操作 在iOS 9之前,所有这些
NSManagedObjectContext
对象的环境。父级context
为并发类型NSMainQueueConcurrencyType
,所有视图控制器都有自己的子级context
对象。我之所以使用这种系统,是因为我希望有更多独立的上下文
,并且只有在我决定应该这样做时才合并它们。子上下文
位于专用队列上,因为它在后线程上执行其工作,然后在主线程上的父上下文
将更改传播到DB,并在主线程上执行其需要的操作
在iOS 9之前,所有这些都运行良好。我的行为很奇怪。例如,当我添加类型为A的新对象时,它会传播到存储器。如果我使用相同的上下文在同一个vc上添加另一个类型为A的对象,但从另一个按钮,则不会调用moc的performBlockAndWait:
,并且我的应用程序在控制台中没有任何消息的情况下冻结。如果尝试使用第一个按钮,它每次都会通过
- (BOOL)saveChildContext:(NSManagedObjectContext*)childContext
{
[childContext performBlockAndWait:^{
NSError* error;
[childContext save:&error];
[_managedObjectContext performBlock:^{
NSError* parentError;
[_managedObjectContext save:&parentError];
}];
}];
}
如果我调用performBlock:
,在这两种情况下一切都很好。所以我发现这可能是由于一些错误的线程。另一方面,使用同一线程处理同一类型的对象,但使用另一个按钮,一切都很顺利。这让我感到困惑,并让人怀疑它与线程有关
我的问题是:
1) 在后台线程上有子context
对象,在主线程上有保存到DB并返回到GUI的context
是正确的方法,还是有更好的约定?如果有,为什么
2) 代码在iOS 8上运行。不过,它似乎不会进入performBlockAndWait:
method。为什么这个块有时不会被执行?是否可能有其他线程正在阻塞?如何确定情况是否如此?在我看来,您的设置并不理想。为什么在视图控制器中使用背景上下文?视图控制器是UI界面,应该使用主上下文
在您的代码示例中,您正在后台线程中使用主上下文,我认为这是有问题的
这是一个运行良好的标准设置(包括iOS9)
通过这种方式,保存到持久性存储总是最后一个,并且总是在后台进行。这是非常安全的,性能良好
我使用临时工作上下文,例如,在从服务器检索后将内容保存在后台队列中,或者处理可以取消的对象编辑(您只需丢弃上下文)。保存工作上下文将更新UI(因为更改会“向上推”到主上下文,主上下文可以通过NSFetchedResultsControllerDelegate
方法或NSNotificationCenter
进行响应) 我发现(谢谢Mundi),我的一个类初始化了自己的NSManagedObjectContext
对象以获取一些数据。后来我从不同的上下文中获取了相关的对象。不知何故,我可以做到这一点,尽管这是不可能的,而且必须避免,即使尝试以这种方式连接对象。始终使用相同的上下文来处理它们之间有关系的对象
因此,我最终使用了childContext=someObjet.managedObjectContext
获取对正确上下文的引用,而不是childContext=[dbClient createChildContext]代码>返回了新的上下文。要解决按钮的特定问题,您必须发布显示两个按钮之间差异的代码。我认为问题可能在于此,因为其他选项从未导致死锁或其他任何问题。不知何故,我使用了两种不同的上下文。我真的不知道我是如何在两个不同上下文获取的两个对象之间建立关系的。更奇怪的是,当我调用asynchronous performBlock:时,它仍然可以毫无问题地访问DB。非常感谢您的评论和建议。正如我所说,我想在另一个线程上执行一些后台任务,为GUI保留主线程。仅使用其他线程是一种解决方案吗?若我总是在主线程上通知GUI分派消息,那个么我可能根本不使用主线程进行数据工作。这是正确的吗?是的。这也包含在我的回答中。是的,你是对的。如果父上下文在主线程上,它将更新GUI,但是如果有很多工作要用DB完成,那么它将在主线程上花费一些时间。另一方面,如果这个耗时的操作在其他线程上,它可以完成它的工作,完成后,它可以只通知主线程,对吗?如果你觉得我的答案有帮助,你至少应该投票给它。当然,对不起。再次感谢你。我讨厌帮助别人得不到荣誉;)
rootContext (Private Queue) --> saves to persistent store --> has child
mainContext (Main Queue) --> used in UI --> has children
workerContext (Private Queue) --> create at will to do background stuff