使用 NSDocument 时如何将情节提要视图绑定到 Core Data 实体?

Posted

技术标签:

【中文标题】使用 NSDocument 时如何将情节提要视图绑定到 Core Data 实体?【英文标题】:How do you bind a storyboard view to a Core Data entity when using NSDocument? 【发布时间】:2016-02-03 02:02:48 【问题描述】:

我正在构建一个使用核心数据、NSDocument、故事板和 Cocoa 绑定的 OS X 应用程序。

我的预期是会发生以下情况:

    创建MyDocumentNSDocument 子类)的实例。

    MyDocument 创建代表文档数据的核心数据NSManagedObjectContext

    MyDocument 通过其标识符从情节提要中实例化 NSWindowController

    在故事板中,窗口控制器包含DocumentEditorViewControllerNSViewController 子类),用于显示和编辑文档。

    在故事板中,DocumentEditorViewController 有一个绑定到MyDocument 的托管对象上下文的NSArrayController

    在故事板中,DocumentEditorViewController 有一个绑定到NSArrayController 的表格视图。

这样,用户界面中的任何更改都会一直到NSManagedObjectContext,而无需任何粘合代码。

我希望这很简单,因为我相信我正在按照它们的预期方式使用这些技术。但是我一直无法让绑定工作,特别是在第 5 步和第 6 步。我发现的所有项目模板和示例项目要么不使用 Core Data,不使用故事板,要么不使用NSDocuments。

哪些对象应该绑定到哪些? NSArrayController 的类、keys 和 keypath 应该是什么?

回答这个问题的另一种方法是指出一个使用所有这些技术的工作示例项目。

【问题讨论】:

您为每个文档使用单独的NSManagedObjectContext?这是 OSX/基于文档的应用程序中推荐的方式吗?在(非基于文档的)ios 应用程序中,我通常使用单个上下文(由应用程序委托拥有),并为每个模型对象使用单独的 NSManagedObject 实例... 我没有看到任何来自 Apple 的示例或指导可以回答您的问题。我认为单独的托管对象上下文更有意义,因为文档是完全独立的。将他们的数据混合到一个上下文中,然后必须过滤对当前视图的数据子集的上下文的所有访问,对我来说没有意义。 您是否尝试过以编程方式添加一些 MOC 对象并查看表视图显示它们的测试用例?如果您尝试将绑定与 AC 创建内容的能力分开调试,则在引用 5 和 6 时不清楚。 @BobWhiteman 您需要将 AC 绑定到上下文并获取特定类型的实体......如果您有智慧,您可以截取 AC 的 IB 配置。它可能是安慰剂,但产品->干净? What is the new way of binding an NSArrayController to the managed object context of a Core Data document?的可能重复 【参考方案1】:

使用 Core Data、Storyboard、NSArrayController、NSTableView 和 Bindings 创建示例 Xcode 基于文档的应用程序项目的步骤。

步骤 1 创建一个 Xcode 项目。选择 OS X Cocoa Application 并选择“Use Storyboards”、“Create Document-Based Application”和“Use Core Data”。

步骤 2 选择数据模型。添加实体“Person”和字符串属性“name”和“address”。

第 3 步 选择 Main.storyboard。将 NSArrayController 添加到视图控制器场景。将模式设置为“实体名称”并将实体名称设置为“人员”。检查“准备内容”。将阵列控制器的Managed Object Context绑定到View Controller,Model Key Path representedObject.managedObjectContext

步骤 4 转到视图控制器场景的视图。删除“您在此处的文档内容”。添加一个 NSTableView。将Content 绑定到Array Controller,控制器密钥arrangedObjects。将Selection Indexes 绑定到Array Controller,控制器密钥selectionIndexes。将Sort Descriptors绑定到Array Controller,控制器密钥sortDescriptors

步骤 5 将表格视图中文本字段的Value 绑定到Table Cell View、Model Key Path objectValue.nameobjectValue.address。选中“有条件地设置可编辑”。

第 6 步 将两个按钮“添加”和“删除”添加到视图控制器场景的视图中。将动作连接到数组控制器的动作add:remove:

第 7 步(目标-C) 选择 Document.h。在方法makeWindowControllers 中,将语句[self addWindowController:… 替换为

NSWindowController *aWindowController = [[NSStoryboard storyboardWithName:@"Main" bundle:nil] instantiateControllerWithIdentifier:@"Document Window Controller"];
[self addWindowController:aWindowController];
aWindowController.contentViewController.representedObject = aWindowController.document;

第 7 步 (Swift) 选择 Document.swift。在方法makeWindowControllers中,在self.addWindowController(windowController)之后的末尾添加

 windowController.contentViewController!.representedObject = windowController.document

第 8 步构建、运行、测试。

【讨论】:

我正准备用您刚刚发布的内容来回答我自己的问题。我的代码中有两个主要错误。一个是不相关的,另一个是新项目模板的问题。它在不实现 KVC 的情况下覆盖了代表对象属性的 didSet 方法。如果你设置 windowController.contentViewController!.representedObject 它工作正常,但如果你将 contentViewController 转换为你的窗口控制器子类的类型,它会破坏 KVO 并且你会得到“Cannot perform operation without a managed object context”错误。 这似乎对我有用,无需在第 4 步中绑定选择索引或排序描述符。你能描述一下为什么需要这些吗? 通过选择索引和排序描述符的绑定,数组控制器和表视图的选择和排序是同步的。阵列控制器的“选择插入的对象”,通过单击列标题进行排序,并将详细视图的元素绑定到阵列控制器的选择将起作用。

以上是关于使用 NSDocument 时如何将情节提要视图绑定到 Core Data 实体?的主要内容,如果未能解决你的问题,请参考以下文章

使用情节提要时如何使用摇动手势?

使用按钮将视图与情节提要中的 tableview 连接

如何将照片(以及标签和按钮)放入滚动视图中,每次在情节提要中添加新照片时都会延长它

如何使用情节提要将集合视图部分项目滚动到水平

如何在多个 .xib 文件之间执行展开转场(不使用情节提要)

iOS - 如何将选项卡与情节提要中的特定视图控制器链接?