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

发布于 2024-11-05 17:48:37 字数 566 浏览 5 评论 0原文

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

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

  1. 将我的操作响应程序放入 NSApplicationDelegate 中。这对我来说似乎很奇怪,部分是因为它位于食物链的顶端,部分是因为它似乎是固定的。

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

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

抱歉问了这么长的问题。有首选方法吗? 谢谢!

So I've spent some time checking out CocoaDev, reading the Cocoa docs on NSMenuItems, and doing some tests in Interface Builder.

In my application I have an application menu ([NSApp mainMenu]) designed in Interface Builder. I see three potential paths:

  1. Put my action responders in the NSApplicationDelegate. This seems strange to me, partially because it's so far up the food chain, partially because it seems bolted on.

  2. Create a sub-view(s) that would listen for the various NSMenuItem action messages. This would seem useful but it looks like in order for it to be in the responder chain there might be some magic I couldn't figure out.

  3. Create an NSObject that listens for the specific application menu stuff, put it in the xib, and wire it up. This seems to me the best solution at the moment, because I can isolate stuff, and not depend upon the responder chain to reach a specific object. BUT I wonder if, when I get my app to a sufficient level of complexity, this may be a problem because it usurps the responder chain, which is there for perhaps a reason beyond just ease of use.

Sorry for the long question. Is there a preferred approach?
Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

铃予 2024-11-12 17:48:37

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

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

  1. 哪个响应程序是第一个响应程序
  2. 视图层次结构
  3. 窗口
  4. 窗口控制器
  5. 窗口委托
  6. NSApp
  7. 应用程序委托

我只在应用程序中使用操作如果它们对于整个应用程序来说确实是全局的,则进行委托。否则,如果它们对特定窗口有意义,我会将它们放入窗口控制器(通常也是窗口委托)中,如果它们对特定视图有意义,则将它们放入视图控制器中。

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

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

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

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

It really depends on the architecture of your application. As a general rule, implement actions wherever they make sense. The responder chain for action messages helps you in that regard.

If your application isn’t document-based, the responder chain for action messages goes like this:

  1. Whichever responder is the first responder
  2. View hierarchy
  3. Window
  4. Window controller
  5. Window delegate
  6. NSApp
  7. Application delegate

I only use actions in the application delegate if they’re truly global for the entire application. Otherwise, I put them in the window controller (which is normally the window delegate as well) if they make sense for a specific window, or a view controller if they make sense for a specific view.

It’s worth mentioning that view controllers (subclasses of NSViewController) aren’t automatically inserted in the responder chain. I do that manually after adding the corresponding view to a superview. For instance, in an NSViewController subclass:

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

This inserts self (an instance of a subclass of NSViewController) in the responder chain between the view and the original view’s next responder.

Note that there’s nothing inherently wrong with your third approach, namely having a specific target for (a subset of) action messages. The responder chain exists to give a chance for different objects to handle action messages because some actions can be context-dependent. For example, the actions under the File menu are normally applied to the window that’s currently the main window, so it makes sense to not have a specific target and use the responder chain instead. On the other hand, the actions under the ApplicationName menu are truly global—they don’t need to go through the responder chain, so you can hook them up to a specific target.

蓝眼泪 2024-11-12 17:48:37

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

I usually just expose IBActions in the app controller (NSApp delegate), and wire the menu items up to those actions. This is a pretty standard way of doing things. If you have a lot of menu items, you can also break the functionality up into one or more controllers that are connected to the app controller, and wire the menu items up to them.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文