为什么 Apple 文档中从 UIApplicationDelegate 获取 ManagedObjectContext 是不好的?

发布于 2024-11-27 01:40:48 字数 157 浏览 0 评论 0原文

只是好奇为什么 ManagedObjectContexts 在创建时应该传递给 UIViewControllers,而不是仅仅从 UIApplicationDelegate 中获取它们?

文档说这会使您的应用程序更加严格,但我看不到何时使用哪种模式的细微差别。

谢谢!

Just curious why ManagedObjectContexts should be passed to UIViewControllers when they are created, rather than just grabbing them from a UIApplicationDelegate?

The docs say that this makes your applications more rigid, but I am failing to see the nuances of when to use which pattern.

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

郁金香雨 2024-12-04 01:40:48

想象一下,我要求你做一些任务,比如粉刷房间。如果我只是告诉你“去粉刷一个房间”,你就需要问我很多问题,比如:

  • 哪个房间?
  • 油漆在哪里?
  • 刷子在哪里?
  • 我应该使用罩布吗?

简而言之,如果没有我的帮助,你将无法完成任务。如果你每次都得依赖我,你就不会成为一个非常灵活的画家。解决这个问题的一种方法是我从一开始就给你提供你需要的所有东西。我不会说“去粉刷一个房间”,而是说“请用这桶油漆和这把刷子粉刷 348 号房间,不要用抹布。”现在,您已拥有所需的一切,无需我的进一步帮助即可开始工作。你是一个更加灵活的员工,因为你不再依赖我。

同样的事情也适用于视图控制器(以及一般的对象);最好为他们提供所需的一切,而不是让他们依赖于应用程序委托等特定对象。这不仅适用于托管对象上下文,也适用于他们完成工作所需的任何信息。

Imagine that I ask you to do some task, like painting a room. If I just tell you "go paint a room," you'll need to ask me a lot of questions, like:

  • Which room?
  • Where's the paint?
  • Where are the brushes?
  • Should I use a dropcloth?

In short, you won't be able to complete the task without help from me. If you have to depend on me every time, you won't be a very flexible painter. One way to deal with that problem is for me to give you all the stuff you need at the outset. Instead of "go paint a room," I'll say "please paint room number 348 using this bucket of paint and this brush, and don't bother with a dropcloth." Now, you've got everything you need, and you can get right to work with no further help from me. You're a much more flexible worker because you no longer depend on me.

The same thing applies to view controllers (and objects generally); it's better to give them everything they need than to have them depend on a particular object like the app delegate. It's true not just for managed object contexts, but for any information they need to do their job.

羁拥 2024-12-04 01:40:48

这主要是因为您希望在 UIViewControllers 中使用依赖注入,而不是仅仅从 UIApplication 中获取所有内容,这可以使您的委托保持干净,而不是充满参考黑客。

这也是为了与 MVC 模式保持一致:

  1. 模型

  2. 视图控制器(仅用于视图逻辑)

  3. 控制器(用于协调视图和模型)

This is mainly because you want to use dependency injection with your UIViewControllers instead of just grabbing everything from UIApplication, this keeps your delegate clean instead of full of reference hacks.

This is also to keep with the MVC pattern:

  1. Model

  2. View Controller (Only for view logic)

  3. Controller (For coordinating between the view and the model)

木森分化 2024-12-04 01:40:48

我倾向于不同意这种模式。

首先,我尝试将核心数据视为实现细节,并且作为任何实现细节,它都应该隐藏在良好的外观后面。外观是我为模型对象公开的接口。例如,如果我有两个模型对象; CourceStudent,任何课程都可以有多个学生。我不想让控制器承担设置谓词和排序描述符的责任,并跳过所有核心数据环只是为了获取特定班级的学生列表。有一种完全有效的方法可以在模型中公开这一点:

@interface Cource (StudentAccess)
-(NSArray*)studentsStortedByName;
@end

然后在 Model 类中一劳永逸地实现丑陋的东西。隐藏核心数据的所有复杂细节,并且无需传递托管对象上下文。但我如何找到来源,它必须从某个地方开始,对吗?是的,确实如此,但您不需要将其暴露给控制器。添加诸如此类的方法也是完全合理的:

@interface Cource (CourceAccess)
+(Cource*)caurceByID:(NSString*)courceID;
+(NSArray*)allCources;
+(NSArray*)courcesHeldByTeacher:(Teacher*)teacher;
@end

这也有助于最大限度地减少控制器之间的依赖关系。并减少模型和控制器之间的依赖性。假设我有一个 CourceViewController 和一个 StudenViewController ,我没有将核心数据细节隐藏在外观后面,并且还想传递托管对象上下文,那么我会结束使用像这样的指定初始化程序:

 -(id)initWithManagedObjectContext:(NSManagedObjectContext*)moc
                           student:(Student*)student;

而有了良好的外观,我最终会得到这样的结果:

 -(id)initWithStudent:(Student*)student;

最小化外观背后的依赖关系,支持依赖注入也使得更改内部实现变得更加容易。传递托管对象上下文鼓励每个控制器为基本内容实现自己的逻辑。以 studentsSortedByName 方法为例。起初,它可能是按姓/名排序,如果后来更改为姓/名排序,您将必须转到每个对学生进行排序的控制器并进行更改。一个好的外观方法需要您更改一种方法,并且所有控制器都会自动免费获得更新。

I tend not to agree with this pattern.

First of all I try to treat Core Data as an implementation detail, and as any implementation detail it should be hidden behind a good facade. The facade is the interfaces I expose for my model objects. For example if I have two model objects; Cource and Student, any cource can have a number of students. I do not want to let the controller take upon the duty to setup predicates and sort descriptors, and jump through all Core Data hoops just to get a list of students for a particular class. There is a perfectly valid way to expose this in the model:

@interface Cource (StudentAccess)
-(NSArray*)studentsStortedByName;
@end

Then implement the ugly stuff once and for all in the Model class. Hiding all the complex details of Core Data, and no need to pass around managed object contexts. But how would I find the sources, it has to start somewhere right? Yes, it does but you need not expose it to the controller. Adding methods such as these are perfectly reasonable as well:

@interface Cource (CourceAccess)
+(Cource*)caurceByID:(NSString*)courceID;
+(NSArray*)allCources;
+(NSArray*)courcesHeldByTeacher:(Teacher*)teacher;
@end

This also helps in minimizing dependencies between controllers. And reducing he dependencies between the model and controller. Assuming I have a CourceViewController and a StudenViewController is I did not hide the Core Data details behind a facade and wanted to pass around the managed object context as well, then I would end up with a designated initializer like this:

 -(id)initWithManagedObjectContext:(NSManagedObjectContext*)moc
                           student:(Student*)student;

Whereas with good a good facade I end up with this:

 -(id)initWithStudent:(Student*)student;

Minimizing dependencies behind facades, in favor of dependency injection also makes it much easier to change the internal implementations. Passing around the managed object context encourages each controller to implement their own logic for basic stuff. Take for example studentsSortedByName method. At first it might be sorter by last/first name, if later changed to last/first name sort you would have to go to each and every controller that has sorted students and make the change. Where a good facade method requires you to change in one method, and all controller automagically get the update for free.

不喜欢何必死缠烂打 2024-12-04 01:40:48

Apple 文档试图培育最广泛适用和可持续的设计模式。
依赖注入是首选,因为它允许最灵活、可扩展、可重用和可维护的设计。

随着应用程序变得越来越复杂,使用准单例(例如将上下文停放在应用程序委托中)就会崩溃。在更复杂的应用程序中,您可能有多个上下文与多个商店相关联。您可能希望相同的视图控制器/视图对在不同时间显示来自不同上下文的数据,或者最终可能会在不同线程/操作上获得多个上下文。您无法将所有这些上下文堆积在应用程序委托中。

如果您有一个具有单个上下文的简单应用程序,那么将准单例与应用程序委托一起使用可以很好地工作。我过去曾在几个较小的应用程序上使用过它,没有立即出现问题,但当应用程序随着时间的推移而增长时,我确实在几个应用程序上遇到了可扩展性问题。

使用哪种模式取决于您的运输限制以及您对进化应用程序在其整个生命周期中的最佳猜测。如果它是一个小型的一次性应用程序,那么应用程序委托准单例将正常工作。如果应用程序更复杂,可能会变得更复杂,或者可能会产生其他将重用现有组件的相关应用程序,那么依赖注入就是正确的选择。

The Apple Docs try to foster the most widely applicable and sustainable design patterns.
Dependency injection is preferred because it allows for the most flexible, expandable, reusable and maintainable design.

As apps grow in complexity, using a quasi-singleton like parking the context in the app delegate breaks down. In more complex apps, you may have multiple context tied to multiple stores. You might want the same view-controller/view pair to display data from different context at different times or you may end up with multiple context on different threads/operations. You can't pile all those context up in the app delegate.

If you have a simple app with a single context then using the quasi-singleton with the app delegate can work well. I've used it on several smaller apps in the past without immediate issue but I did hit scalability problems on a couple of apps when the apps grew overtime.

Which pattern to use depends on your shipping constraints and you best guesses about of the evolution app over its entire lifecycle. If its a small one shot app, then the app delegate quasi-singleton will work fine. If the app is more complex, might grow more complex or might spawn other related apps that will reuse existing components, then dependency injection is the way to go.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文