如何获取viewController的managedObjectContext,而不是从appDelegate获取?

最近我开始知道“你真的不应该调用AppDelegate来获取托pipe对象上下文”。 苹果公司也把这个build议放在他们的文档里 。 它是这样的:

视图控制器通常不应该从全局对象(如应用程序委托)中检索上下文,这使得应用程序架构变得僵化。 视图控制器也不应该为它自己的用途创build一个上下文(除非它是一个嵌套的上下文)。 这可能意味着使用控制器的上下文执行的操作不会注册到其他上下文中,因此不同的视图控制器将对数据有不同的观点。

此外,他们还提到了一些其他方法来获得背景。 到目前为止,我无法弄清楚他们想在那里说些什么。 任何人都可以提出这个问题。 任何代码片段支持声明将是最受欢迎的。

编辑

但有时,从应用程序或文档或视图控制器以外的地方检索上下文会更容易或更合适。 您可能在基于核心数据的应用程序中使用的几个对象保留对托pipe对象上下文的引用。 一个托pipe对象本身有一个对自己的上下文的引用,支持核心数据的各种控制器对象(例如数组和对象控制器(OS X中的NSArrayController和NSObjectController,以及iOS中的NSFetchedResultsController))也是如此。

从其中一个对象中检索上下文具有如下优点:如果重新构build应用程序,例如使用多个上下文,则代码可能保持有效。 例如,如果您有一个托pipe对象,并且要创build一个与之相关的新托pipe对象,则可以向原始对象请求托pipe对象上下文,并使用该对象创build新对象。 这将确保您创build的新对象与原始对象处于相同的上下文中。

究竟是什么? 相信它与下面Highly投票答案不相似。 有人能帮我理解这部分苹果文件吗?

它被称为dependency injection。 基本上调用者/构造函数应该将NSManagedObjectContext设置为调用/构造。

在您的AppDelegate您应该将NSManagedObjectContext设置为与UIWindow关联的rootViewController

你的rootViewController应该设置NSManagedObjectContext到下一个视图控制器等。

怎么样? 这只是一个简单的适当的视图控制器类和调用方使用:

 [nextViewController setManagedObjectContext:[self managedObjectContext]]; 

其他人可能会推荐一个单身人士,但这是另一个深深的黑洞,最好避免。

更新

dependency injection是最好的方法。

这是苹果devise的方法。 另一种select涉及某种forms的单例:AppDelegate或另一种。

“在控制器之间传递相同的上下文的缺点是,如果在两个不同的地方修改同一个实体,则必须pipe理合并冲突。

这是一个完全不同的问题,它不会用多个NSManagedObjectContext实例解决。 事实上,多个实例会使情况变得更糟,并保证合并冲突。

在这种情况下,你的视图控制器应该监听被pipe理对象的变化并对它们作出反应。 无法在UI中同时在两个地方更新它。 用户根本无法一次将注意力集中在两个地方,因此第二个地点将实时更新。

这是这个问题的正确答案。

两个实体在相同的上下文将确保正常工作。 多个上下文将使它们成为内存中具有相同数据的两个对象,并且无法在没有保存到上下文的情况下注意到这些更改。

但是,如果您有视图控制器正在修改数据而无需用户干预,那么您有一个单独的问题。 视图控制器供用户修改或查看数据。 他们不是任何types的数据后台处理的地方。

如果你处于import情况,那么这是一个不同于你问的问题。 在这种情况下,您应该使用多个线程(UI线程,导入线程),并且每个线程必须至less有一个上下文。

在这种情况下,你确实冒着合并冲突的风险,你需要为发生的情况编码。 第一步是更改NSManagedObjectContext实例上的合并策略。

更新

我怀疑你误解了这个文档。

所描述的是从NSManagedObject实例中获取NSManagedObjectContext的能力。 这是绝对有用的。 以一个视图控制器为例,它可以添加或编辑一个对象。 通过推动NSManagedObject到视图控制器,你可以控制和决定什么视图控制器将触摸。 接收视图控制器知道它需要允许编辑接收到的NSManagedObject 。 它不关心它正在处理什么NSManagedObjectContext 。 它可以与主体一起工作,可以和孩子一起工作,也可以在unit testing中隔离,不需要知道或关心。 它只是显示NSManagedObject的数据,如果用户select保存编辑,则保存相关的NSManagedObjectContext

该文件不build议拥有一些通用的位置为您的NSManagedObjectContext生活(又名单身人士)。 这是暗示,如果你有另一种方式来访问与NSManagedObjectContext关联的NSManagedObject ,那么可以这么做,这样做肯定是有意义的。

在抓取我的Managed Object Context时,单例方法对我来说效果最好。 这实际上取决于你的应用程序的复杂性,但在我的情况下,我通常保留一个托pipe对象上下文,并在需要进行更改时使用临时嵌套的上下文。

通过使用一个基于单例的“DataManager”类,它包含所有的Core Data初始化方法和公共引用的Managed Object Model和Context,我可以通过导入我的“DataManager.h”类并调用单身人士:

 // I have a method to create an object that requires the Manage Object Context, so I call it from the DataManager singleton SomeObject *newObject = [SomeObject createObjectInContext:[[DataManager sharedInstance] managedObjectContext]]; // I have a method in DataManager to save the context [[DataManager sharedInstance] saveContext]; 

这实际上是简化的版本。 我通常使用嵌套的托pipe对象上下文,以便我的主要托pipe对象上下文不会被修改,直到用户确认添加或修改托pipe对象。 这个复杂性可以全部包含在“DataManager”类中。

这有点偏离主题,但是如果您需要了解更多关于嵌套上下文的信息:当不使用嵌套上下文来更改主要的上下文对象时,我遇到了严重的问题。 这篇文章,虽然其中的一部分,我的头,帮助我理解和实施嵌套上下文:

http://www.cocoanetics.com/2012/07/multi-context-coredata/