将 NSArrayController 绑定到 Core Data 文档的托管对象上下文的新方法是什么?

What is the new way of binding an NSArrayController to the managed object context of a Core Data document?

在 Xcode 为 OS X 应用程序添加故事板之前,您可以通过将数组控制器的 Managed Object Context 绑定到 [= 来将数组控制器连接到文档的托管对象上下文11=] 的 Model Key PathmanagedObjectContext。有了情节提要,就没有更多 File's Owner 那么您现在从哪里获得上下文?

Apple 的文档在这方面落后,Xcode 中没有任何明显的地方可以绑定。显然我可以退回到非故事板路线并使用旧方法,但必须有一种新的方法。

如果应用程序委托拥有核心数据堆栈,您始终能够通过键路径 delegate.managedObjectContext 通过 NSApplication 进行绑定。否则,您可以将 MOC 传递给每个视图控制器,每个视图控制器上都有一个 MOC 属性,这是那些认为不应使用应用程序委托来拥有单例 MOC 的人的强烈偏好,并且还有进一步的能够为每个 VC 提供单独的 MOC 的实用程序。

我相信您也可以在 IB 的故事板中创建一个 MOC 实例。至少,对于笔尖也一直有一个 MOC 对象。虽然我还没有充分使用它来了解它与程序化核心数据堆栈的关系。最好在某个地方拥有一个 MOC 属性,您可以在 VC 层次结构或应用程序委托

中访问

所以我从 Apple 那里得到了答案。这是针对基于文档的核心数据应用程序,代码全部在 Swift 中,但想法与 Objective-C 中的相同,您只需翻译它即可。

他们给我的第一个答案是将数组控制器绑定到视图控制器 运行 模型键路径为 self.view.window.windowController.document.managedObjectContex 的视图。我看到的示例使用了这种方法并且根本没有错误消息,但是它是 window 控制器内的单个视图控制器和一个数组控制器。我的设置是 window 到选项卡视图到一个场景中有两个阵列控制器的视图。每次打开或创建新文档时,我仍然得到 Cannot perform operation without a managed object context 一次。对我有用的第二个解决方案是仍然将数组控制器绑定到视图控制器,但模型键路径为 self.representedObject.managedObjectContext,然后添加到文档 class 的末尾 makeWindowControllers()函数:

override func makeWindowControllers() {
……
    let tabViewController = windowController.contentViewController as NSTabViewController
    for object in tabViewController.childViewControllers {
        let childViewController = object as NSViewController
        childViewController.representedObject = self
    }
}

这解决了我的问题。希望这里有足够的信息可以在其他人 google 这个问题时出现。

使用默认 Xcode 生成的项目并包括 CoreData 将 managedObjectContext 成员放在 AppDelegate 上。您可以将以下代码添加到您的 ViewController,然后使用 managedObjectContext 作为 "Model Key Path",并为您的 NSArrayController.

绑定到 ViewController
lazy var managedObjectContext: NSManagedObjectContext = { 
    return (NSApplication.sharedApplication().delegate
        as? AppDelegate)?.managedObjectContext }()!

这只是创建一个成员,该成员重定向到您实际存储 MOC 的位置。这很有用,因为 NSArrayController 绑定发生在 viewDidLoad() 之前,因此实例成员是不够的。此外,如果您想重构为单例 CoreDataManager class,您只需更改重定向到的位置即可。此外,您可以将其添加为 class 扩展,以使所有 ViewControllers 能够访问您的 MOC。

Objective-C 根据要求提供版本:

@interface MyViewController ()

@property (nonatomic, readonly) NSMangedObjectContext* managedObjectContext;

@end

@implementation MyViewController

- (NSManagedObjectContext*)managedObjectContext
{
    return ((AppDelegate*)([NSApplication sharedApplication].delegate)).managedObjectContext;
}

...

@end

已更新:

@theMikeSwan,好吧,它几乎对我有用。这是我拥有的:

OSX EL Capitan GM Xcode 7GM 和 Xcode 7.1 测试版

一个标准Coredata/Document应用程序

用 TabViewController 替换了 MainViewController 并向其添加了 2 个 ViewController。

添加到您的代码中以将 representedObject 放入 tabviewcontroller 的所有视图控制器中。

第一个选项卡是一个带有 table 的视图控制器,以及一个绑定到名为 Profiles 的实体的数组控制器,table视图通过 +/- 等绑定到该控制器

选项卡二是带有视图控制器的视图,视图控制器带有 table,数组控制器绑定到名为 Commands 的实体,table视图绑定到该控制器。

配置文件和名称为配置文件 <->> 命令的命令实体之间存在一对多关系。

两个选项卡都按预期工作,独立没有错误 - 这意味着我可以在第一个选项卡的 table 中添加和删除 Profiles->name,我可以在 table 在第二个选项卡中。

接下来我想强制执行一对多关系 - 这意味着如果我 select 选项卡 1 中 table 中的配置文件,然后切换到选项卡二,我只想看到与 table 中的 selected 配置文件相关的命令。那是行不通的。所有输入的Command在所有情况下都显示出来,我尝试过filters predicates,fetch predicates等,都有不同程度的灾难。

我已经尝试了所有我能想到的方法,还有很多我不想提及的技巧 -

此时我已将第二个 arrayController 添加到第二个选项卡视图并将其绑定到 Profiles 实体并使用 self.representedObject.managedObjectContext 等...我在第二个选项卡视图上添加了一个 NSTextField 并将其绑定到刚刚添加了 profileArrayController -> selection -> name 以查看控制器在想什么...

无论我在第一个选项卡 table 中 select 是什么,第二个选项卡中的配置文件->名称永远不会改变,它始终显示相同的配置文件->名称。第二个选项卡 table 中列出的命令不受第一个 table.

中任何 selection 的影响

它 "feels" 第二个选项卡上的 MOC 与第一个选项卡引用的 MOC 不同。但这只是一种感觉。我迷路了,关于如何在像这样的多选项卡视图控制器设置上跨选项卡建立一对多关系有什么建议吗?

谢谢 弗兰克

编辑添加:

顺便说一句,我在其中一些选项卡上有多个 tables 配置在同一个选项卡上的一对多关系中,这些关系正常工作 - 例如我有一个同义词 table 通过数组控制器绑定到同义词实体,数组控制器是与命令实体关系的多方面。只要 tables/arraycontrollers 在同一个选项卡上,它就可以正常工作,但是当在不同的选项卡上时,它就没有乐趣了。