将"核心数据堆栈"放在Cocoa/Cocoa Touch应用程序中的位置

Cor*_*oyd 67 iphone cocoa cocoa-touch core-data

在iPhone核心数据模板中,Apple将核心数据堆栈放在App Delegate中.

然而,我最初的倾向是将此代码移动到它自己的类中,该类的职责是处理核心数据堆栈的管理.

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

mma*_*alc 39

简介:无需创建单例来管理Core Data堆栈; 确实这样做可能会适得其反.

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

这里描述的单体的典型作用是作为模型控制器.使用Core Data,托管对象上下文已经是模型控制器.它还使您能够在需要时访问堆栈的其他部分.此外,在某些情况下(如文档中所述),您可能希望使用不同的上下文来执行一组离散的操作.因此,视图控制器的适当货币单位通常是托管对象上下文,否则是托管对象.使用和传递管理堆栈的单个对象(以及从中检索上下文)通常最多会引入不必要的间接层,最坏的情况是引入不必要的应用程序刚性.

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

[[UIApplication delegate] managedObjectContext];
Run Code Online (Sandbox Code Playgroud)

  • @VictorEngel如果视图控制器是由故事板创建的,那么您是否找到了应该如何传递上下文?IT是如此令人沮丧,以至于每个人都说不要从应用代表那里得到它,但是不说一句话,那么你应该如何获得这个背景? (3认同)
  • 当我第一次开始使用Core Data时,不使用依赖注入绝对是一个糟糕的设计.最近,我采用了与您概述的相同的方法.主要的区别在于我已经将核心数据堆栈代码放在NSManagedObject Context的类别中,如果只是为了在逻辑上将Core Data堆栈代码与AppDelegate分开.从理论上讲,我可以使用类似单身人士的类别,但我选择不这样做,因为它引入了"应用程序刚性",如你所说.另外,我为Core Data堆栈使用了一些自定义代码,这使我可以轻松地将此代码放入新项目中. (2认同)

Dan*_*iel 28

我有一个单例类,我让我的核心数据管理,我不会留在应用程序代表.我宁愿不要使用我可能需要的方法来混淆应用委托类,例如获取某些对象等

  • 他们可能会这样做,因为他们想要展示如何做到这一点,那就是他们虽然它是方便的地方放置它,因为应用代表已经是一种单身人士 (4认同)
  • 拥有单个核心数据控制器对象是完全有道理的.我们将它抽象出来,以便它可以在每个项目中重复使用.+1 (3认同)
  • 我同意(a)有一个通用的核心数据管理类,更容易放入项目(特别是已经存在的项目)和(b)它总是在AppDelegate中作为例子的原因是他们试图尽量减少尽可能使用非示例代码 - 所以为什么在AppDelegate以免费方式(代码长度方面)表现时会创建一个完整的单例.我把它放在一个单例中,这样只有处理Core Data的类与单例有任何联系,这也意味着更少的类也必须包含App Delegate标题. (2认同)

Mas*_*aro 11

我将核心数据逻辑留在App委托中,原因如下:

1)我认为在其他类中移动此代码没有任何真正的优势:由于核心数据模型实际上是应用程序的基本部分,因此由App委托处理的核心数据逻辑完全实现了委派的概念.

2)在我看到的所有示例代码中,包括Apple示例,核心数据内容由App代表处理;

3)即使在核心数据书籍中,通常的做法是让App委托处理与核心数据相关的代码;

4)我个人并不认为通过为核心数据设置临时类来实际提高可读性或其他任何东西,但这是个人品味的问题,我不会在这里争论哪种方法是最好的方法.对我而言,保持功能的简单性非常重要.

  • 我还认为参数2和3是因为在教程或示例中,您试图尽可能地减少与您尝试呈现的内容无关的任何代码 - 因此实现Singleton的机制会增加太多的开销.应该是一个简单的例子.我不喜欢将这些东西保存在App Delegate中,因为它增加了必须知道的关于App Delegate的事情的数量...... (3认同)

Ale*_*lex 10

在你的情况下,我问自己的问题是"核心数据堆栈属于谁"?数据本身真的是应用程序的省份,不是吗?(Mac上的CF Core Data,您可能拥有一次能够处理多个文档的应用程序,因此Core Data堆栈属于每个文档.)

在任何Cocoa/Cocoa Touch应用程序中,App Delegate通常是自定义应用程序行为的首选方法,因此这是Core Data堆栈的自然位置.

现在,我怀疑你遇到的问题是经常写下这样的事情是错误的:

NSManagedObjectContext *context = [(MyAppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
Run Code Online (Sandbox Code Playgroud)

在这些情况下我通常做的是写函数(不是方法),如下所示:

NSManagedObjectContext *UIAppManagedObjectContext() {
    return [*(MyAppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
}
Run Code Online (Sandbox Code Playgroud)

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

  • 那很好笑.这正是我不喜欢的代码片段.我不喜欢运行App Delegate来获取文件存储信息.感觉"错了".这让我怀疑其他开发者如何处理这种情况. (2认同)
  • 您应该*不*从这样的应用程序委托中获取上下文.您应该将一个上下文从一个视图控制器传递到下一个视图控制器,如Apple的所有示例所示. (2认同)

Cor*_*oyd 6

我将在新的答案中列出这一点.(我已经废弃了我以前的FJSCoreDataStack类而不赞成这个)

我处理这个问题的新方法是在NSManagedObjectContext上使用一个类别.我添加了以下类方法:

+ (NSManagedObjectContext *)defaultManagedObjectContext;
+ (NSManagedObjectContext *)scratchpadManagedObjectContext;
+ (NSManagedObjectModel *)managedObjectModel;
+ (NSPersistentStoreCoordinator *)persistentStoreCoordinator;
+ (NSString *)applicationDocumentsDirectory;
Run Code Online (Sandbox Code Playgroud)

这可以保留我的应用程序委托中的所有内容,并且如果我选择使用它,则会提供单例访问权限.但是,我仍然使用来自App Delegate的依赖注入(正如mmalc所说,它在我的代码中引入了不灵活性).我只是将所有"核心数据堆栈"代码移动到NSManagedObjectCOntext类别中.

我喜欢传递引用,特别是因为我有一个很好的"暂存器上下文"方法.这使我的视图控制器保持灵活,因为我还没有将它们提交给"defaultManagedObjectContext".

也与iPhone世界中的对话相关(并且可能与您的架构有关): NSFetchedResultsController和构建NSFetchRequests