从Interface Builder连接NSMenuItems的最佳方法?

时间:2011-05-06 21:22:41

标签: objective-c nsmenuitem first-responder

所以我花了一些时间查看CocoaDev,阅读NSMenuItems上的Cocoa文档,并在Interface Builder中进行一些测试。

在我的应用程序中,我有一个在Interface Builder中设计的应用程序菜单([NSApp mainMenu])。我看到了三条潜在的路径:

  1. 将我的操作响应程序放在NSApplicationDelegate中。这对我来说似乎很奇怪,部分原因是因为它远远超过了食物链,部分原因是因为它看起来像是狂奔。

  2. 创建一个可以侦听各种NSMenuItem操作消息的子视图。这似乎很有用,但看起来为了让它在响应链中可能会有一些我无法弄清楚的魔法。

  3. 创建一个NSObject,用于侦听特定的应用程序菜单内容,将其放入xib中,然后将其连接起来。这在我看来是目前最好的解决方案,因为我可以隔离东西,而不依赖于响应者链来达到特定对象。但是我想知道,当我的应用程序达到足够高的复杂程度时,这可能是一个问题,因为它篡夺了响应者链,这可能是一个超出易用性的原因。

  4. 很抱歉这个问题很长。有首选方法吗? 谢谢!

2 个答案:

答案 0 :(得分:7)

这实际上取决于应用程序的体系结构。作为一般规则,在任何有意义的地方实施行动。在这方面,响应者行动消息链可以帮助您。

如果您的应用程序不是基于文档的,则操作消息的响应者链如下所示:

  1. 无论哪个响应者是第一响应者
  2. 查看层次结构
  3. 窗口
  4. 窗口控制器
  5. 窗口委托
  6. NSApp
  7. 申请代表
  8. 我只在应用程序委托中使用操作,如果它们对整个应用程序来说真的是全局的。否则,我将它们放在窗口控制器(通常也是窗口委托)中,如果它们对特定窗口有意义,或者视图控制器对特定视图有意义。

    值得一提的是,视图控制器(NSViewController的子类)不会自动插入响应器链中。我将相应的视图添加到superview后手动执行此操作。例如,在NSViewController子类中:

    NSResponder *nextResponder = [[self view] nextResponder];
    [[self view] setNextResponder:self];
    [self setNextResponder:nextResponder];
    

    这会在视图和原始视图的下一个响应者之间的响应者链中插入selfNSViewController的子类的实例)。

    请注意,您的第三种方法没有任何内在错误,即为(一部分)动作消息设定特定目标。响应者链的存在是为了让不同的对象有机会处理动作消息,因为某些动作可能与上下文有关。例如,“文件”菜单下的操作通常应用于当前主窗口的窗口,因此没有特定目标并使用响应程序链是有意义的。另一方面,ApplicationName菜单下的操作是真正全局的 - 它们不需要通过响应者链,因此您可以将它们连接到特定目标。

答案 1 :(得分:0)

我通常只是在app控制器(IBActions委托)中公开NSApp,然后将菜单项连接到这些操作。这是一种非常标准的做事方式。如果你有很多菜单项,你也可以将功能分解为一个或多个连接到app控制器的控制器,并将菜单项连接到它们。