【问题标题】:Starting a Cocoa document-based application shows selection window first启动一个基于 Cocoa 文档的应用程序首先显示选择窗口
【发布时间】:2011-04-23 15:04:14
【问题描述】:

这似乎应该很容易,但我一定错过了一些东西。我有一个基于文档的应用程序。我还构建了一个新的 XIB,上面有一个 NSTableView 和三个按钮,我打算显示以前文件的列表。我希望在应用程序首次启动时显示此 XIB 而不是文档窗口。一旦用户选择了一个旧文件或点击“新建”按钮,我希望然后转到文档窗口。这是很常见的,我经常看到。

为了让这个工作正常,我修改了 project-info.plist 文件,并将主 NIB 文件基本名称从 MyDocument 更改为我的选择 XIB 名称。这会导致应用程序显示选择窗口而不是 MyDocument 窗口。到目前为止,似乎没有任何问题。

在我的选择窗口中,我已经为这个 XIB 设置了我的表格视图和一个数组控制器和一个自定义窗口控制器。我已将文件的所有者设置为新的窗口控制器,并将窗口控制器的窗口属性绑定到窗口,将窗口的委托属性绑定到文件的所有者以及“选择”、“取消”和“新建”按钮。没有任何东西与 NSApplication 绑定。但奇怪的是,当我运行这个应用程序时,它似乎想将这些控制器连接到 NSApplication 并出现错误(其他两个按钮相同):

无法将动作 selectButton: 连接到类 NSApplication 的目标

它还显示一个错误,即 NSApplication 对于持有对我的数组的引用的插座不符合键值对。 Array Controller、Window 和按钮没有绑定到 NSApplication,而是绑定到新的 Window Controller。我本来希望如果有任何问题不会提到 NSApplication 而是控制器绑定到的窗口控制器。

有人知道这里发生了什么吗?这是一个 Target-Action 问题,因为我将“Main NIB File Base Name”从“Main Menu”更改为“Selection”?如果我不应该更改它,那么如何让 Cocoa 允许我在显示文档窗口之前显示一个选择屏幕?

非常感谢任何帮助。 抢

【问题讨论】:

    标签: cocoa xib cocoa-bindings document-based


    【解决方案1】:

    在 IB 中对 nib 的 File's Owner 类的设置只是建议性的;它让 IB 只显示该类的实例提供的出口和操作。它不强制文件的所有者将是该类的实例,因为文件的所有者不是 nib 的一部分。

    文件的所有者是加载 nib 的对象。 这必然意味着它在 nib 之外,并且 nib 中的任何内容都无法决定它。 在 MainMenu nib 的情况下,它的 File's Owner(加载 MainMenu nib 的对象)是NSApplication 实例。因此,您在 MainMenu nib 中连接到文件所有者的所有内容都连接到应用程序对象,即使您告诉 IB 它不是应用程序。

    应用程序是 MainMenu nib 的所有者——不管你告诉 IB 什么——不是错误。应用程序始终是 MainMenu nib 的所有者。这是正常和正确的;你不能改变它,不应该尝试改变它,也不需要改变它。

    简而言之,错误在于您将一个笔尖用于两个截然不同的目的。

    您应该让 MainMenu nib 单独存在 - 仅包含 MainMenu、您的自定义文档控制器(我稍后会介绍)和您的应用程序委托 - 并将上一个文档窗口移动到单独的 nib ,由先前的文档窗口控制器拥有。为了让窗口控制器成为这个 nib 的所有者,您需要让窗口控制器加载它。您必须在代码中执行此操作——您无法在 IB 或 plist 中进行设置。

    在应用程序的委托中,实例化并拥有窗口控制器。听起来您创建了一个自定义 NSWindowController 子类,因此您可以覆盖它的 init 让它自己发送 initWithWindowNibName: 消息以加载并拥有 nib。然后,只需使用allocinit 从应用委托创建窗口控制器。

    这将消除控制台消息,并确保按钮实际连接到窗口控制器(因为它们连接到文件所有者,通过此更改,它将成为窗口控制器)。

    让您的应用代理通过向窗口控制器发送showWindow: 消息来响应applicationOpenUntitledFile:。这将使以前的文档窗口出现在用户通常创建新文档的任何时候。

    如果你想支持创建文档的常用方法(即允许新建文档工作),那么实现applicationDidFinishLaunching:applicationShouldHandleReopen:hasVisibleWindows:,而不是applicationOpenUntitledFile:。确保没有打开任何文档,如果是这样,请显示您的窗口。

    您还应该创建一个 NSDocumentController 的自定义子类,并让您的文档控制器成为它的一个实例,并在该类中实现 addDocument:removeDocument: 以在最后一个打开的文档时重新显示上一个文档窗口关闭,并在打开文档时将其隐藏。

    【讨论】:

    • 这很有帮助。让我失望的是使用核心数据的文档应用程序不会自动创建应用程序委托。一旦我创建了委托,我就可以停止自动创建,然后打开我的初始窗口。非常感谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多