iOS 9中的核心数据存在问题我在iOS 8中没有。
我有一个包含多个NSManagedObjectContext
个对象的环境。父context
具有并发类型NSMainQueueConcurrencyType
,并且所有视图控制器都有自己的子context
个对象。我使用这种系统的原因是因为我希望有更多的独立contexts
并且只有在我决定应该完成时才合并它们。子context
位于私有队列中,因为它在后台线程上工作,然后是父context
,它在主线程上将更改传播到DB并在主线程上执行它所需的操作。
所有这些在iOS 9之前都运行良好。我得到的行为很奇怪。例如,当我添加类型A的新对象时,它会传播到存储。如果我在同一个vc上添加另一个类型为A的对象,使用相同的context
,但是从另一个按钮,moc的performBlockAndWait:
没有被调用,我的应用程序在控制台中没有任何消息时冻结。如果尝试使用第一个按钮,它每次都会通过。
- (BOOL)saveChildContext:(NSManagedObjectContext*)childContext
{
[childContext performBlockAndWait:^{
NSError* error;
[childContext save:&error];
[_managedObjectContext performBlock:^{
NSError* parentError;
[_managedObjectContext save:&parentError];
}];
}];
}
如果我拨打performBlock:
,两种情况都可以。所以我发现这可能是由于一些错误的线程造成的。另一方面,使用相同类型的对象相同的线程,但另一个按钮,一切都很顺利。这让我感到困惑,并且怀疑它与线程有关。
我的问题:
1)在反向线程上使用子context
对象是正确的方法,并且context
保存到DB并在主线程上返回GUI,或者是否有更好的约定,以及如果有,为什么?
2)代码在iOS 8上运行。但是,似乎它不会输入performBlockAndWait:
方法。为什么这个区块有时不会被执行?是否有可能其他一些线程阻塞?如何判断是否属实?
答案 0 :(得分:1)
在我看来,您的设置并不理想。为什么在视图控制器中使用背景上下文?视图控制器是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
通过这种方式,保存到持久性存储始终是最后的,并且始终在后台进行。这非常安全且性能良好。
我使用 ad hoc 工作者上下文,例如从服务器检索后保存在后台队列上的东西,或处理可以取消的对象编辑(你只是扔掉上下文)。保存工作者上下文将更新UI(因为更改是"向上推动"到主要上下文,可以通过例如NSFetchedResultsControllerDelegate
方法或NSNotificationCenter
进行响应。
答案 1 :(得分:0)
我想通了(谢谢Mundi)我的一个类初始化了自己的NSManagedObjectContext
对象来获取一些数据。后来我将相关的对象从不同的上下文中获取。不知何故,我可以这样做,虽然它不可能,甚至必须避免尝试以这种方式连接对象。始终使用相同的上下文来处理在它们之间有关系的对象。
所以,我最终使用childContext = someObjet.managedObjectContext;
来获取对正确上下文的引用,而不是返回新上下文的childContext = [dbClient createChildContext];
。