【发布时间】:2011-07-31 04:12:44
【问题描述】:
只是好奇为什么 ManagedObjectContexts 应该在创建时传递给 UIViewControllers,而不是仅仅从 UIApplicationDelegate 中获取?
文档说这会使您的应用程序更加僵化,但我看不出何时使用哪种模式的细微差别。
谢谢!
【问题讨论】:
标签: ios core-data nsmanagedobjectcontext
只是好奇为什么 ManagedObjectContexts 应该在创建时传递给 UIViewControllers,而不是仅仅从 UIApplicationDelegate 中获取?
文档说这会使您的应用程序更加僵化,但我看不出何时使用哪种模式的细微差别。
谢谢!
【问题讨论】:
标签: ios core-data nsmanagedobjectcontext
想象一下,我请你做一些任务,比如粉刷一个房间。如果我只是告诉你“去粉刷一个房间”,你需要问我很多问题,比如:
简而言之,如果没有我的帮助,您将无法完成任务。如果你每次都要依靠我,你就不会是一个很灵活的画家。解决这个问题的一种方法是让我在一开始就给你所有你需要的东西。而不是“去粉刷一个房间”,我会说“请用这桶油漆和这把刷子粉刷 348 号房间,不要用抹布。”现在,你已经拥有了你需要的一切,你可以在没有我进一步帮助的情况下开始工作。你是一个灵活得多的工人,因为你不再依赖我。
同样的事情也适用于视图控制器(以及一般的对象);最好给他们所需的一切,而不是让他们依赖于像应用程序委托这样的特定对象。这不仅适用于托管对象上下文,而且适用于他们完成工作所需的任何信息。
【讨论】:
这主要是因为您希望将dependency injection 与您的 UIViewController 一起使用,而不是仅仅从 UIApplication 中获取所有内容,这样可以使您的委托保持干净而不是充满参考黑客。
这也是为了符合 MVC 模式:
型号
视图控制器(仅用于视图逻辑)
控制器(用于视图和模型之间的协调)
【讨论】:
我倾向于不同意这种模式。
首先,我尝试将 Core Data 视为一个实现细节,并且作为任何实现细节,它应该隐藏在一个好的外观之后。外观是我为模型对象公开的接口。例如,如果我有两个模型对象; Cource 和 Student,任何课程都可以有多个学生。我不想让控制器承担设置谓词和排序描述符的职责,并跳过所有 Core Data 箍来获取特定班级的学生列表。有一种完全有效的方法可以在模型中公开它:
@interface Cource (StudentAccess)
-(NSArray*)studentsStortedByName;
@end
然后在 Model 类中一劳永逸地实现丑陋的东西。隐藏 Core Data 的所有复杂细节,无需传递托管对象上下文。但是我该如何找到来源,它必须从正确的地方开始?是的,确实如此,但您无需将其暴露给控制器。添加这样的方法也是非常合理的:
@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 方法为例。起初它可能是按姓/名排序的,如果后来更改为姓/名排序,您将不得不去每个对学生进行排序的控制器并进行更改。一个好的外观方法需要您更改一种方法,并且所有控制器都会自动免费获得更新。
【讨论】:
Course 类的类方法中提取课程列表而感到羞耻。将类视为单例。
Apple Docs 试图培养最广泛适用和可持续的设计模式。 依赖注入是首选,因为它允许最灵活、可扩展、可重用和可维护的设计。
随着应用程序复杂性的增加,使用准单例(如将上下文停放在应用程序委托中)会出现问题。在更复杂的应用程序中,您可能会将多个上下文关联到多个商店。您可能希望相同的视图控制器/视图对在不同时间显示来自不同上下文的数据,或者您最终可能会在不同线程/操作上获得多个上下文。您不能将所有这些上下文堆积在应用程序委托中。
如果您有一个具有单一上下文的简单应用程序,那么将准单例与应用程序委托一起使用可以很好地工作。我过去曾在几个较小的应用程序上使用过它,但没有立即出现问题,但是当应用程序超时增长时,我确实在几个应用程序上遇到了可伸缩性问题。
使用哪种模式取决于您的运输限制以及您对进化应用在整个生命周期内的最佳猜测。如果它是一个小型的一次性应用程序,那么应用程序委托准单例就可以正常工作。如果应用程序更复杂,可能会变得更复杂,或者可能会产生其他相关的应用程序来重用现有组件,那么依赖注入就是要走的路。
【讨论】: