【问题标题】:How to connect a menu item to a custom action defined in the NSApplication delegate across nib files?如何跨 nib 文件将菜单项连接到 NSApplication 委托中定义的自定义操作?
【发布时间】:2011-09-13 06:47:35
【问题描述】:

在我的 Cocoa 应用程序中,我需要连接两个 NIB/XIB 文件:

  1. MainMenu.xib:包含 NSApplication 委托对象的自定义对象,并将其连接到 NSApplication 占位符中的正确插座。

  2. ContextMenu.xib:设置一个NSMenu;一个条目应该打开首选项对话框

我的自定义应用委托定义了一个IBAction 来为我的应用打开“首选项”窗口。

如何连接 NSMenuItem(第二个 NIB)以显示应用程序委托(第一个 NIB)中定义的操作的首选项?

Docs 说这应该很容易,但他们没有提到如何在 Interface Builder 中准确地做到这一点:

如果菜单项引用应用程序级命令,您可以 直接在应用程序委托中实现该命令,或者只是 让委托将消息转发给适当的对象 应用程序中的其他位置。

不知何故,我需要访问第二个 NIB 中的应用程序委托,告诉 Interface Builder 它属于我的自定义类(因此它知道自定义 IBAction),并将其连接到菜单项的操作。

感谢您的指点!

【问题讨论】:

标签: cocoa interface-builder xib nsmenuitem nsapplication


【解决方案1】:

如果其他对象在响应者链中,那么您只需将操作连接到第一个响应者。

不过,请注意“如果”。

正如 Maurice Kelly 所提到的,您的 App Delegate 已经是响应者链的一部分,因此您可以使用它:在 First Responder(在 Interface Builder 中)上定义一个自定义操作,并在您的 App Delegate 上定义一个相应的操作。但是,如果您有许多操作可能会使 App Delegate 混乱,那么您可能只想将此架构用于简单的应用程序。

【讨论】:

    【解决方案2】:

    对于第二个 NIB 中的绑定,可以通过使用以 delegate 开头的模型密钥路径绑定到 Application 来访问应用程序委托绑定。即delegate.managedObjectContext

    警告:不要在第二个 NIB 中创建应用程序委托对象。如果这样做,您最终会得到第二个应用程序委托实例和第二个单独的 managedObjectContext。 NIB 创建另一个应用程序委托对象。这太可怕了。

    在加载 MainMenu.xib 时,[NSApplication sharedApplication] 将其委托设置为在 MainMenu.xib 中实例化的委托对象。如果您在另一个 NIB 中创建委托对象,您将拥有一个与 [NSApp delegate] 不匹配的委托对象。 (而且你会把头撞到墙上,试图找出上下文视图没有更新的原因)

    【讨论】:

      【解决方案3】:

      您的第二个 NIB 将有一个文件所有者,您应该将其设置为由您的应用程序实例化的类。在此类中,您可以创建对 App Delegate 的引用,可以在实例化类时填写该引用(例如,如果您是从委托中创建它,则使用 setAppDelegate:self)。

      在此类中创建一个 IBAction,它只是将操作传递给 App Delegate:

      - (IBAction) passItOnAction:(id)sender {
          [appDelegate openPreferences:sender];
      }
      

      【讨论】:

      • 糟糕 - 刚刚看到您的编辑。我不确定是否有替代文件所有者操作绕道的方法。文件的所有者是一个代理对象,您的 NIB 可以通过它与在它的小世界之外创建的对象进行通信。
      • 我希望避免绕道/passItOn 风格(这就是我目前所拥有的)。有没有办法将应用代理添加为代理对象或排序?
      • 嗯,我不认为你可以添加更多的代理对象。但是,我想您可以让应用程序代表您的第二个 NIB 的文件所有者。我不确定这会产生什么影响。
      • 我没有在上面发表评论的声誉,但@Monolo 的回答似乎还不错。您的 App Delegate 应该是 Responder Chain 的一部分,因此在 First Responder 上定义自定义操作以及您的 App Delegate 上的相应操作应该可以工作。我已经在一个示例项目(非基于文档)上进行了尝试,它对我有用。
      • 好的,我根据您对 Monolo 回答的评论添加了更多详细信息。谢谢!
      【解决方案4】:

      我遇到了同样的问题,然后这样解决了:

      • 我只创建了一个菜单 (MainMenu.xib)。由于第一响应者未提供任何操作的菜单项会自动显示为灰色,因此在激活“首选项”窗口时,用于“文档”窗口的项目将显示为灰色。

      • 我为首选项窗口的定义创建了 PrefsWin.xib。该 xib 的 File's Owner 是一个名为 PrefsWinController 的类,它继承自 NSWindowController。

      • MainMenu.xib 中的操作只是连接到第一响应者而不是委托。如果您的 实例是 NSResponder 的实例,则委托将自动充当链中的最后一个响应者。 (我不知道这可能会记录在哪里,但它确实适用于我的项目。)

      【讨论】:

      • App delegate 的行为就像一个响应者,即使它不是从 NSResponder 继承的,你可以在 Event Architecture 中找到 Apple 文档,对于 Responder Chain for Action Messages 部分。
      猜你喜欢
      • 1970-01-01
      • 2016-02-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多