使用 NSDocument 时如何将故事板视图绑定到核心数据实体?

How do you bind a storyboard view to a Core Data entity when using NSDocument?

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

我预计会发生以下情况:

  1. MyDocumentNSDocument subclass)的实例已创建。

  2. MyDocument 创建一个代表文档数据的核心数据 NSManagedObjectContext

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

  4. 在故事板中,window 控制器包含 DocumentEditorViewControllerNSViewController subclass),用于显示和编辑文档。

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

  6. 在故事板中,DocumentEditorViewController 有一个绑定到 NSArrayController 的 table 视图。

这样 UI 中的任何更改都会一直到 NSManagedObjectContext,无需任何胶水代码。

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

哪些对象应该绑定到哪些? NSArrayController 的 class、键和键路径应该是什么?

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

创建示例Xcode 具有核心数据、故事板、NSArrayController、NSTableView 和绑定的基于文档的应用程序项目的步骤。

步骤 1 创建一个 Xcode 项目。选择 OS X Cocoa 应用程序和 select“使用故事板”、“创建基于文档的应用程序”和“使用核心数据”。

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

步骤 3SelectMain.storyboard。将 NSArrayController 添加到视图控制器场景。将模式设置为“实体名称”并将实体名称设置为“人”。检查“准备内容”。将阵列控制器的 Managed Object Context 绑定到 View Controller,模型键路径 representedObject.managedObjectContext.

第四步进入视图控制器场景的视图。删除“您的文档内容在这里”。添加一个 NSTableView。将 Content 绑定到 Array Controller,控制器密钥 arrangedObjects。将 Selection Indexes 绑定到 Array Controller,控制器密钥 selectionIndexes。将 Sort Descriptors 绑定到 Array Controller,控制器密钥 sortDescriptors

步骤 5 将 table 视图中的文本字段 Value 绑定到 Table Cell View,模型键路径 objectValue.nameobjectValue.address。检查 'Conditionally Sets Editable'.

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

步骤 7 (Objective-C) Select 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) Select Document.swift。在方法 makeWindowControllers 中,在 self.addWindowController(windowController) 之后添加

 windowController.contentViewController!.representedObject = windowController.document

步骤 8 构建,运行,测试。