Cocoa / Cocoa Touch应用程序中的“核心数据栈”的放置位置


67

在iPhone Core Data模板中,Apple将Core Data Stack放置在App Delegate中。

但是,我的初衷是将这段代码移到其自己的类中,该类负责处理核心数据栈的管理。

您通常将此功能封装在其自己的类中还是将其保留在App Delegate中?

Answers:


39

简介:无需创建一个单一实例即可管理核心数据堆栈。确实这样做可能适得其反。

核心数据堆栈恰巧是由应用程序委托创建的。但是,重要的是,如所有示例所示,并不是直接从stack(*)检索堆栈(主要是托管对象上下文)。而是将上下文传递到第一个视图控制器,并将上下文或托管对象从上下文将它们从一个视图控制器传递到下一个视图控制器(如访问核心数据栈中所述)。这遵循iPhone所有应用程序的基本模式:将数据或模型控制器从一个视图控制器传递到下一个视图控制器。

如此处所述,单例的典型角色是作为模型控制器。对于Core Data,托管对象上下文已经是模型控制器。如果需要,它还使您能够访问堆栈的其他部分。此外,在某些情况下(如文档中所述),您可能希望使用其他上下文来执行一组离散操作。因此,视图控制器的适当货币单位通常是托管对象上下文,否则是托管对象。使用和传递管理堆栈(并从中检索上下文)的单例对象通常最多会引入不必要的间接级别,最坏的情况会带来不必要的应用程序僵化。

(*)没有示例使用以下方法检索上下文:


2
当我第一次开始使用Core Data时,不使用依赖注入绝对是一个糟糕的设计。最近,我采用与您概述的方法相同的方法。主要区别在于,即使只是为了从AppDelegate逻辑上分离核心数据堆栈代码,我还是将NSCoredObject Context中的类别放入了核心数据堆栈代码。从理论上讲,我可以像单例一样使用类别,但我选择不这样做,因为它会像您所说的那样引入“应用程序刚性”。此外,我为Core Data堆栈使用了一些自定义代码,这使我可以轻松地将此代码放入新项目中。
Corey Floyd 2010年

1
我与您一起使用App Delegate创建Core Data堆栈。我使用UITabBarController作为我的根视图控制器,我不确定如何将上下文传播到该控制器对象,因为它位于MainWindow.xib中,并且不确定如何为它分配指向ManagedObjectContext的指针。我想我为此发布了一个单独的问题。
mvexel 2010年

1
该Apple文档说:“创建视图控制器时,将其应使用的上下文传递给它。” 但我看不到如何完成。主视图控制器是通过情节提要(如果使用情节提要)创建的,对吗?那么如何传递上下文呢?
Victor Engel

3
@VictorEngel那么,您是否发现如果情节提要创建视图控制器,应该如何传递上下文?IT实在令人沮丧,以至于到处都有人说不要从应用程序委托中获取信息,而没有说出您应该如何获得上下文?
Madhu

如果您查看Apple的模板,则视图控制器具有上下文的可变属性。可以使用上下文的第一个视图控制器在didFinishLaunchingWithOptions中设置了它。从那时起,它被传递给每个后续的视图控制器。文档中也对此进行了介绍。
2014年

28

我有一个单例课程,可以让我做我的核心数据管理,而且我不把它留在应用程序委托中。我宁愿不要使用我可能需要说服性的方法(例如,获取某些对象等)来使应用程序委托类混乱


1
对我来说听起来很实用。我很惊讶苹果将其包含在应用程序委托中。
科里·弗洛伊德

4
他们之所以这样做,是因为他们想展示如何做到这一点,那就是他们放哪儿的地方,因为应用程序委托已经有点单身了
Daniel Daniel

3
具有单例核心数据控制器对象完全有意义。我们对其进行了抽象,以便可以在每个项目中重复使用。+1
stigi

1
我现在也为Core Data堆栈使用一个singleton类。我认为它的行为类似于通知中心或共享用户默认值,您可以在其中调用[[DatabaseController sharedDatabaseController] writableManagedObjectContext]以在需要时获取特定上下文。回调给应用程序委托以获取堆栈似乎很麻烦。
布拉德·拉尔森

2
我同意(a)具有通用的核心数据管理类,该类更容易放入项目中(尤其是已经存在的项目),并且(b)例如,它始终存在于AppDelegate中的原因是,他们试图将其尽量减少尽可能地使用非示例代码-那么当AppDelegate免费以行为方式(就代码长度而言)时,为什么要使整个单身。我将其放在一个单例中,以便仅处理Core Data的类与该单例有任何联系,这也意味着更少的类也必须包含App Delegate标头。
肯德尔·赫尔姆斯特·盖尔纳

11

由于以下原因,我将核心数据逻辑留在了App委托中:

1)在其他类别中移动此代码时,我看不出任何真正的优势:委派的概念完全由App委托处理的核心数据逻辑实现,因为核心数据模型实际上是应用程序的基础部分;

2)在我看到的所有示例代码中,包括Apple示例,核心数据都是由App委托处理的;

3)即使在Core Data书籍中,让App委托人处理与核心数据相关的代码也是一种惯例;

4)就个人而言,我不认为通过为核心数据设置临时类实际上可以提高可读性或其他任何功能,但这是个人喜好的问题,在这里我不会争论哪种方法是最佳方法。对我来说,保持功能的简单性很重要。


我通常还会在App Delegate中看到Core Data堆栈。但是,我查看的代码通常是出于说明目的而创建的。实现某些内容的实际方法有时与此类示例有所不同。我不想无缘无故地盲目遵循Apple的示例代码。我倾向于认为您是对的,认为这只是个人喜好,无论哪种方式都有一些优势。
科里·弗洛伊德

3
我也认为参数2和3是因为在教程或示例中您试图尽可能地减少与所要呈现的内容无关的任何代码-因此实现Singleton的机制会增加太多开销应该是一个简单的例子。我不喜欢将这些内容保留在App Delegate中的原因是,它增加了随后必须了解的有关App Delegate的内容...
Kendall Helmstetter Gelner 09年

“由于核心数据模型实际上是应用程序的基本组成部分,因此由App委托处理的核心数据逻辑完美地实现了委托的概念;” 不,UIApplication不会将对核心数据功能的任何委托委派给它的委托。您可能会确定持久性存储是应用程序级别的问题,但它不是UIApplicationDelegate的一部分。
2014年

10

在您的情况下,我会问自己一个问题:“核心数据堆栈属于谁?” 数据本身确实是应用程序的一部分,不是吗?(在Mac上,CF Core Data可能具有一个可以同时处理多个文档的应用程序,因此Core Data堆栈属于每个文档。)

在任何Cocoa / Cocoa Touch应用程序中,“应用程序委托”通常是自定义应用程序行为的首选方法,因此,这是“核心数据”堆栈的自然位置。

现在,我怀疑您遇到的问题是不断写类似的东西是错误的:

在这些情况下,我通常要做的是这样的写函数(而不是方法):

我为NSPersistentStoreCoordinator和编写了类似的函数NSManagedObjectModel。我将所有这些都放在App Delegate的.h / .m文件中,因为它们也是应用程序级对象。


2
那很好笑。那正是我不喜欢的代码。我不喜欢运行App Delegate来获取文件存储信息。感觉“不对”。这使我怀疑其他开发人员如何处理这种情况。
科里·弗洛伊德

1
第一个代码段感觉不对的原因是因为它具有代码气味。用方便的功能包装只是除臭剂。简单地将上下文传递给需要上下文的对象要简单得多(主要是使用属性注入)。
路加·雷德帕特

2
您不应该这样从应用程序委托获取上下文。您应该将上下文从一个视图控制器传递到下一个视图控制器,如所有Apple的示例所示。
mmalc 2011年

反对使用应用程序代理
Jake Vizzoni 2012年

6

我将在新答案中列出。(我为此废弃了以前的FJSCoreDataStack类)

我处理此问题的新方法是在NSManagedObjectContext上使用类别。Ive添加了以下类方法:

这将所有内容排除在我的应用程序委托之外,并在我选择使用它时提供单例访问。但是,我仍然使用来自App Delegate的依赖项注入(如mmalc所说,它在我的代码中引入了不灵活性)。我只是将所有“核心数据栈”代码移到了NSManagedObjectCOntext类别中。

我喜欢传递参考,尤其是因为我有一个不错的“便签本上下文”方法。因为我没有将它们提交给“ defaultManagedObjectContext”,所以这使我的视图控制器保持灵活。

也与iPhone世界中的对话有关(可能与您的体系结构有关): NSFetchedResultsController和构造NSFetchRequests


4

我赞成让应用程序委托知道模型从哪里开始,并让模型知道托管对象上下文在哪里。模型的核心数据“感觉”对我来说似乎是模型的实现细节,控制器类(如应用程序委托)应该问“向我提供有关模型的信息”,并且模型应该知道如何回答这个问题。因此,通过控制器对象可以使用Core Data对象似乎是一种泄漏抽象。


在iPhone开发中已经成为问题的是使用和配置NSFetchedResultsControllers。现在,您还可以让“模型”如何配置和返回NSFetcheResultsControllers,但看来模型类会有点肿。我感觉像NSFetchedResultsControllers模糊了控制器和模型代码之间的界线(不一定是不好的方式)。我最近已将此和其他一些想法纳入我的新配置(添加了新答案)。
科里·弗洛伊德

我同意@Graham,这就是我的做法。您UIViewControllers不需要弄乱NSManagedObjectContext,他们只需要与模型对话并询问他们需要什么。获取信息的机制与我的视图控制器无关。
kubi 2011年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.