我在 iOS 9 中遇到了我在 iOS 8 中没有的 Core Data 问题。
我的环境中有多个 NSManagedObjectContext
对象。家长 context
是并发类型NSMainQueueConcurrencyType
并且所有 View Controller 都有自己的 child context
对象。我之所以使用这种系统是因为我想拥有更多独立的contexts
并仅在我决定应该完成时才合并它们。 child context
位于私有(private)队列上,因为它在后端线程上工作,然后是父级 context
,它在主线程上将更改传播到 DB 并在主线程上执行它需要的操作。
在 iOS 9 之前,所有这些都运行良好。我得到的行为相当奇怪。例如,当我添加 A 类型的新对象时,它会传播到存储。如果我在同一个 vc 上添加另一个类型 A 的对象,使用相同的 context
但从另一个按钮,performBlockAndWait:
moc 没有被调用,我的应用程序在控制台中没有任何消息卡住。如果尝试使用第一个按钮,它每次都会通过。
- (BOOL)saveChildContext:(NSManagedObjectContext*)childContext
{
[childContext performBlockAndWait:^{
NSError* error;
[childContext save:&error];
[_managedObjectContext performBlock:^{
NSError* parentError;
[_managedObjectContext save:&parentError];
}];
}];
}
如果我调用
performBlock:
,在这两种情况下一切都很好。所以我发现这可能是由于一些错误的线程。另一方面,使用具有相同类型对象的相同线程,但使用另一个按钮,一切都很顺利。这让我感到困惑,并让人怀疑它与线程有关。我的问题:
1) 是正确的生 child 方式
context
后线程上的对象,并具有 context
保存到数据库并返回到主线程上的 GUI,或者是否有更好的约定,如果有,为什么?2) 该代码在 iOS 8 上运行。不过,它似乎不会输入
performBlockAndWait:
方法。为什么这个 block 有时不被执行?是否有可能其他线程正在阻塞?如何确定是否是这种情况?
最佳答案
在我看来,您的设置并不理想。为什么在 View Controller 中使用背景上下文? View Controller 是 UI 界面,应该使用主上下文。
在您的代码示例中,您在后台线程中使用主上下文,我认为这是有问题的。
这是一个运行良好的标准设置(包括 iOS9)。
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
以这种方式保存到持久存储总是最后并且总是在后台发生。这是非常安全且性能良好的。
我使用临时工作人员上下文,例如从服务器检索后将内容保存在后台队列中,或处理可以取消的对象编辑(您只需丢弃上下文)。保存工作人员上下文将更新 UI(因为更改被“推送”到可以通过例如
NSFetchedResultsControllerDelegate
方法或 NSNotificationCenter
响应的主上下文)。
关于multithreading - iOS 9 核心数据线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32744375/