2015-09-23 75 views
4

我有iOS中9核心数据有问题,我没有在iOS的8的iOS 9核心数据线程

我有多个NSManagedObjectContext对象的环境。父context是并发类型NSMainQueueConcurrencyType,并且所有视图控制器都有自己的子对象context。我使用这种系统的原因是因为我想拥有更多独立的contexts,并且只有在我决定完成时才合并它们。子context在私有队列上,因为它在后面的线程上工作,然后在父主线context上工作,父主线程将更改传播到数据库并在主线程上完成它所需的工作。

所有这一切都很好,直到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是保存到数据库,再返回到GUI上的主线,还是有更好的惯例的正确方法,并如果有的话,为什么?

2)代码在iOS 8上工作。但是,它似乎不会输入performBlockAndWait:方法。为什么有时这个块不会被执行?是否有其他线程阻塞?如何找出这是否是这种情况?

+0

要解决您的按钮的特定问题,您必须发布显示两个按钮之间区别的代码。 – Mundi

+0

我认为问题可能在于,因为其他选项从未造成死锁或其他任何事情。不知何故,我使用了两种不同的上下文。我真的不知道我是如何设法建立由两个不同的上下文获取的两个对象之间的关系。还有一点很奇怪的是,当我调用异步performBlock时,它仍然没有问题地到达DB。 –

回答

0

我想通了(谢谢蒙迪),我的一个类初始化了自己的NSManagedObjectContext对象来获取一些数据。后来我将从不同上下文中获取的对象关联起来。不知何故,我可以做到这一点,尽管它不应该是可能的,并且必须避免尝试以这种方式连接对象。总是使用相同的上下文来处理它们之间有关系的对象。

所以,我结束了使用childContext = someObjet.managedObjectContext;获得正确的上下文的参考,而不是childContext = [dbClient createChildContext];返回新的上下文。

+0

如果你发现我的答案有帮助,你至少应该对它投票。 – Mundi

+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进行响应的主要上下文)。

+0

非常感谢您的意见和建议。正如我所说的,我想在另一个线程上执行一些后台任务,为GUI保留主线程。只能使用其他线程是一种解决方案吗?如果我总是在主线程上通知GUI dispaching消息,我可能根本不会使用主线程进行数据工作。它是否正确? –

+0

是的。这也被封装在我的答案中。 – Mundi

+0

是的,你说得对。如果父上下文位于主线程上,它会更新GUI,但是如果使用DB需要做很多工作,那么在主线程上需要一些时间。另一方面,如果这个耗时的操作在其他线程上,它可以完成它的工作,并且在完成之后,它可能只是通知主线程,对吧? –