最近我开始知道“你真的不应该调用AppDelegate来获取托管对象上下文”。 Apple也已将此建议纳入其文档here。 它是这样的:
视图控制器通常不应从全局对象(例如应用程序委托)检索上下文 - 这会使应用程序体系结构变得僵硬。视图控制器也不应为自己的用途创建上下文(除非它是嵌套的上下文)。这可能意味着使用控制器上下文执行的操作未在其他上下文中注册,因此不同的视图控制器将对数据有不同的视角。
此外,他们还提到了其他一些获取背景的方法。到目前为止,我无法弄清楚他们在那里想说些什么。任何人都可以对这个问题有所了解。任何支持语句的代码片段都是最受欢迎的。
修改
但有时,检索它更容易或更合适 来自应用程序或文档以外的某个地方的上下文 查看控制器。您可能在基于Core Data的数据中使用的几个对象 应用程序保持对托管对象上下文的引用。管理 对象本身具有对其自身上下文的引用,各种各样 支持Core Data的控制器对象,例如数组和对象 控制器(OS X中的NSArrayController和NSObjectController,以及 iOS中的NSFetchedResultsController。
从其中一个对象中检索上下文具有优势 如果你重新设计你的应用程序,例如使用 多个上下文,您的代码可能仍然有效。例如, 如果您有托管对象,并且想要创建新的托管对象 与它相关的对象,你可以问原始对象 托管对象上下文并使用它创建新对象。这将 确保您创建的新对象与 原始
究竟是什么?我确定它与下面的Highly投票答案不相似。有人可以帮我理解这部分Apple文档吗?
答案 0 :(得分:39)
它被称为依赖注入。基本上调用者/构造函数应该将NSManagedObjectContext
设置为被调用/构造。
在AppDelegate
中,您应将NSManagedObjectContext
设置为与rootViewController
相关联的UIWindow
。
然后,您的rootViewController
应将NSManagedObjectContext
设置为下一个视图控制器,依此类推。
如何?它只是一个简单的视图控制器类,调用者使用:
[nextViewController setManagedObjectContext:[self managedObjectContext]];
其他一些人可能会推荐单身,但这是另一个最好避免的深坑。
依赖注入是最好的方法。
这是Apple设计的方法。另一种选择涉及某种形式的单身人士:AppDelegate或另一种。
“在控制器之间传递相同的上下文的缺点是,如果在两个不同的地方修改了同一个实体,则必须管理合并冲突。”
这是一个完全不同的问题,不将通过多个NSManagedObjectContext
实例解决。实际上,多个实例会使情况变得更糟并保证合并冲突。
在这种情况下,您的视图控制器应该监听托管对象中的更改并对它们做出反应。无法在UI中同时在两个位置更新它。用户根本无法一次关注两个地方,因此第二个位置将实时更新。
这是该问题的正确答案。
将两个实体放在同一个上下文中将确保其正常工作。多个上下文将导致它们在内存中具有相同数据的两个对象,并且无法在不保存到上下文的情况下注意到更改。
但是,如果您的视图控制器正在修改数据而无需用户干预,则您会遇到单独的问题。视图控制器供用户修改或查看数据。它们不是进行任何数据后台处理的地方。
如果您处于进口情况,那么这与您提出的问题不同。在这种情况下,您(应该)使用多个线程(UI线程,导入线程),必须至少有一个上下文。
在这种情况下,您确实存在合并冲突的风险,您需要为发生的情况编写代码。第一步是更改NSManagedObjectContext
实例上的合并策略。
我怀疑你误读了这些文档。
所描述的是能够从NSManagedObjectContext
实例中获取NSManagedObject
的能力。这绝对有用。例如,可以添加或编辑对象的视图控制器。通过将 NSManagedObject
推送到视图控制器,您可以控制并决定该视图控制器将要触摸的内容。接收视图控制器知道它需要允许编辑接收的NSManagedObject
。它并不关心它正在使用NSManagedObjectContext
。它可能与主要工作,它可能与一个孩子一起工作,它可能在单元测试中孤立,它不需要知道或关心。它只显示来自NSManagedObject
的数据,如果用户选择保存修改,则会保存关联的NSManagedObjectContext
。
该文档并未建议您为NSManagedObjectContext
生活(也称为单身人士)提供一些通用位置。建议如果您有另一种方式来访问与NSManagedObjectContext
相关联的NSManagedObject
,那么这样做是绝对有意义的。
答案 1 :(得分:0)
在抓取我的托管对象上下文时,单例方法最适合我。这实际上取决于应用程序的复杂性,但在我的情况下,我通常会保留一个托管对象上下文,并在需要进行更改时使用临时嵌套上下文。
通过使用包含所有Core Data初始化方法的基于单例的“DataManager”类以及对托管对象模型和上下文的公共引用,我可以通过导入“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];
这实际上是简化版。我通常使用嵌套的托管对象上下文,以便在用户确认添加或修改托管对象之前不会修改我的主托管对象上下文。这种复杂性都可以包含在“DataManager”类中。
这有点偏离主题,但是如果您需要了解有关嵌套上下文的更多信息:当不使用嵌套上下文来更改主受管对象上下文时,我遇到了严重问题。这篇文章,虽然其中一些超越我的头,帮助我理解和实现嵌套的上下文: