除了从 appDelegate 获取之外,如何为 viewController 获取 managedObjectContext? [英] How to get managedObjectContext for viewController other than getting it from appDelegate?

查看:20
本文介绍了除了从 appDelegate 获取之外,如何为 viewController 获取 managedObjectContext?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

最近我开始知道你真的不应该调用 AppDelegate 来获取托管对象上下文".Apple 也将此建议写入了他们的文档 此处.它是这样的:

<块引用>

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

此外,他们还提到了其他一些获取上下文的方法.到目前为止,我无法弄清楚他们在那里想说什么.任何人都可以请说明这个问题.任何支持语句的代码片段都将受到欢迎.

编辑

<块引用>

不过,有时更容易或更合适地检索来自应用程序或文档以外的其他地方的上下文,或视图控制器.您可能会在基于 Core Data 的项目中使用的几个对象应用程序保持对托管对象上下文的引用.一个托管对象本身有一个对它自己的上下文的引用,就像各种支持核心数据的控制器对象,例如数组和对象控制器(OS X 中的 NSArrayController 和 NSObjectController,以及iOS 中的 NSFetchedResultsController).

从这些对象之一中检索上下文具有优势如果你重新设计你的应用程序,例如利用在多个上下文中,您的代码很可能保持有效.例如,如果您有一个托管对象,并且您想创建一个新的托管对象将与之相关的对象,您可以向原始对象询问其托管对象上下文并使用它创建新对象.这会确保您创建的新对象与原创.

究竟是什么?我确信它与下面的高票答案不相似.有人可以帮我理解这部分 Apple 文档吗?

解决方案

这叫做依赖注入.基本上,调用者/构造函数应该将 NSManagedObjectContext 设置到被调用/构造函数上.

在您的 AppDelegate 中,您应该将 NSManagedObjectContext 设置到与 UIWindow 关联的 rootViewController 中.

您的 rootViewController 然后应该将 NSManagedObjectContext 设置为下一个视图控制器,依此类推.

怎么样?它只是视图控制器类上的一个简单的属性,调用者使用:

[nextViewController setManagedObjectContext:[self managedObjectContext]];

有些人可能会推荐单身人士,但这是另一个最好避免的深坑.

更新

依赖注入是最好的方法.

这是 Apple 设计的方法.另一种选择涉及某种形式的单例:AppDelegate 或其他.

<块引用>

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

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

在这种情况下,您的视图控制器应该监听托管对象中的更改并对其做出反应.使其无法在 UI 中同时在两个位置更新.用户根本无法同时关注两个地方,因此第二个位置将实时更新.

这是该问题的正确答案.

将两个实体置于同一上下文中将确保其正常工作.多个上下文将导致它们成为内存中具有相同数据的两个对象,并且在不保存到上下文的情况下无法注意到更改.

但是,如果您的视图控制器在没有用户干预的情况下修改数据,那么您就会遇到一个单独的问题.视图控制器供用户修改或查看数据.它们不是对数据进行任何类型的后台处理的地方.

如果您处于进口情况,那么这与您提出的问题不同.在这种情况下,您(应该)使用多个线程(UI 线程、导入线程)并且您必须为每个线程至少有一个上下文.

在这种情况下,您确实存在合并冲突的风险,并且您需要针对发生的情况进行编码.第一步是更改 NSManagedObjectContext 实例上的合并策略.

更新

我怀疑您误读了该文档.

所描述的是从 NSManagedObject 实例中获取 NSManagedObjectContext 的能力.这绝对有用.以具有添加或编辑对象能力的视图控制器为例.通过将只是 NSManagedObject 推送到视图控制器,您可以控制并决定该视图控制器将要接触的内容.接收视图控制器知道它需要允许编辑接收到的 NSManagedObject.它不关心它正在使用什么 NSManagedObjectContext.它可以与主要一起工作,它可以与孩子一起工作,它可以在单元测试中被隔离,它不需要知道或关心.它只是显示来自 NSManagedObject 的数据并保存相关的 NSManagedObjectContext 如果用户选择保存编辑.

该文档并不建议为您的 NSManagedObjectContext 提供一些通用位置(也称为单例).这表明,如果您有另一种方法来访问与 NSManagedObject 关联的 NSManagedObjectContext,那么这样做是可以的,而且这样做绝对有意义.>

Recently I came to know that "You really shouldn't be calling down to the AppDelegate to get the managed object context". Apple also has put this recommendation into their documentation here. It goes like this :

A view controller typically shouldn’t retrieve the context from a global object such as the application delegate—this makes the application architecture rigid. Neither should a view controller create a context for its own use (unless it’s a nested context). This may mean that operations performed using the controller’s context aren’t registered with other contexts, so different view controllers will have different perspectives on the data.

Further they have mentioned some other ways to get context. So far I am unable to figure out what they are trying to say there. Can anybody please put some light on the issue. Any code snippet supporting statements would be most welcome.

EDIT

Sometimes, though, it’s easier or more appropriate to retrieve the context from somewhere other than application or the document, or the view controller. Several objects you might use in a Core Data-based application keep a reference to a managed object context. A managed object itself has a reference to its own context, as do the various controller objects that support Core Data such as array and object controllers (NSArrayController and NSObjectController in OS X, and NSFetchedResultsController in iOS).

Retrieving the context from one of these objects has the advantage that if you re-architect your application, for example to make use of multiple contexts, your code is likely to remain valid. For example, if you have a managed object, and you want to create a new managed object that will be related to it, you can ask original object for its managed object context and create the new object using that. This will ensure that the new object you create is in the same context as the original.

What exactly it is? Am sure its not similar with the Highly voted answer below. Can somebody help me to understand this portion of Apple documents?

解决方案

It is called dependency injection. Basically the caller/constructor should be setting the NSManagedObjectContext onto the called/constructed.

In your AppDelegate you should set the NSManagedObjectContext into the rootViewController that is associated with the UIWindow.

Your rootViewController should then set the NSManagedObjectContext into the next view controller and so on.

How? It is just a simple proper on the view controller class and the caller uses:

[nextViewController setManagedObjectContext:[self managedObjectContext]];

Some others may recommend a singleton but that is another deep dark pit that is best avoided.

Update

Dependency Injection is the best approach.

It is the approach Apple has designed around. The other choice involves some form of a singleton: AppDelegate or another one.

"The downside of passing the same context between controllers is that if a same entity is modified in two different places, you have to manage the merge conflict."

That is a completely different problem and it is not going to be solved with multiple NSManagedObjectContext instances. In fact, multiple instances will make the situation worse and guarantee a merge conflict.

In that situation, your view controllers should be listening for changes in the managed object and reacting to them. Making it impossible to update it in two places at once in the UI. The user simply cannot focus on two places at once and therefore the second location will be updated in real time.

That is the right answer for that problem.

Having both entities in the same context will make sure that works correctly. Multiple contexts will cause their to be two objects in memory with the same data and no way to notice the changes without a save to the context.

However, if you are having view controllers that are modifying data without user intervention then you have a separate problem. View controllers are for the user to modify or view data. They are not the place for any kind of background processing of the data.

If you are in an import situation then that is a different question than the one you asked. In that case you are (should be) using multiple threads (UI thread, import thread) and you must have at least one context for each.

In that situation you do risk a merge conflict and you need to code for the situation happening. First step is to change the merge policy on the NSManagedObjectContext instances.

Update

I suspect you are misreading that documentation.

What that is describing is the ability to get the NSManagedObjectContext out of the NSManagedObject instance. This is absolutely useful. Take for example a view controller that has the ability to add or edit an object. By pushing just the NSManagedObject to the view controller you can control and decide what that view controller is going to be touching. The receiving view controller knows that it needs to allow editing of the received NSManagedObject. It does not care what NSManagedObjectContext it is working with. It could be working with the main, it could be working with a child, it could be in isolation in a unit test, it doesn't need to know or care. It simply displays the data from the NSManagedObject it is handed and saves the associated NSManagedObjectContext if the user chooses to save the edits.

That documentation is NOT suggesting having some universal location for your NSManagedObjectContext to live (aka a singleton). It is suggesting that if you have another way to access the NSManagedObjectContext that is associated with a NSManagedObject that it is ok to do so and definitely makes sense to do so.

这篇关于除了从 appDelegate 获取之外,如何为 viewController 获取 managedObjectContext?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆