在基于文档的 OS X 应用程序中的 NSViewController 上设置 representedObject

Set representedObject on an NSViewController in a document-based OS X application

我正在开发一个简单的 OS X Cocoa 应用程序,用户在其中填写表单,应用程序执行一些计算,这些计算会在其他字段中弹出。

我从 Xcode 6.3.2(对于 Yosemite)上的默认基于文档的应用程序模板开始。这个模板包括一个NSDocument的子类和一个NSViewController的子类。该界面在 Storyboard 中定义。 NSDocument 在 makeWindowControllers 中从 Storyboard 初始化界面。

我 运行 遇到了将接口片段绑定到 ViewController 的表示对象的问题——结果我绑定到了 nil。 ViewController 的 setRepresentedObject 方法从未被调用。

我尝试在 viewDidLoad 中对自身调用 ViewController setRepresentedObject,但是 WindowController 的文档 属性 尚未设置(返回 nil)。

我不清楚是否可以从 NSDocument 中获取 ViewController 的实例 - NSDocument 知道它的 window/WindowController,但我不确定如何找到ViewController 来自 类.

我想知道执行此操作的惯用 Xcode/Apple 方法。无论是通过 Storyboard 视图还是在我的代码中以编程方式实现。

我还想尽可能避免将代码耦合得太紧。

我能够通过覆盖 NSViewController 的 viewWillAppear 方法来设置视图控制器的表示对象,该方法似乎是在将文档实例设置为 window 文档之后调用的。

- (void)viewWillAppear {
    [super viewWillAppear];

    // Set up the document as the data source
    NSLog(@"viewWillAppear");
    NSWindow *myWindow = [[self view] window];
    NSWindowController *myWindowController = [myWindow windowController];
    CharacterSheetDocument *myDocument = [myWindowController document];
    [self setRepresentedObject: [myDocument characterData]];
}

我不知道这是否是最简洁的方法,但它确实有效。

视图控制器不仅遍历一系列嵌套的 getter 来查找模型对象,而且还了解文档子类的所有信息,这似乎有点笨拙。

当我 运行 回答这个问题时,我只是想自己解决这个问题。在 ViewController class 的 viewWillAppear 方法中执行此操作(如 wolfteeth 所建议)使 ViewController 依赖于 Document 对象,这对我来说似乎是倒退的。

最好在文档 class 的 makeWindowControllers 方法中执行此操作,如下所示:

override func makeWindowControllers() {
    // Returns the Storyboard that contains your Document window.
    let storyboard = NSStoryboard(name: "Main", bundle: nil)
    let windowController = storyboard.instantiateController(withIdentifier: "Document Window Controller") as! NSWindowController
    self.addWindowController(windowController)

    // Set represented object of ViewController
    if let viewController: ViewController = windowController.contentViewController as! ViewController? {
        viewController.representedObject = self.model
    }
}

此代码片段假定您的文档 class 中有一个名为 "model" 的 属性,它引用了您的 ViewController 代表的模型对象。