上下文菜单不调用 NSMenuDelegate 方法
Posted
技术标签:
【中文标题】上下文菜单不调用 NSMenuDelegate 方法【英文标题】:NSMenuDelegate methods not called for contextual menu 【发布时间】:2013-06-04 03:38:30 【问题描述】:我有一个基于文档的应用程序。我想添加一个上下文菜单,当用户右键单击 NSTextView 中的选定文本时显示上下文相关信息。
我已按照Apple documentation 中的建议和
在我的 XIB 文件中添加了一个 NSMenu 作为根对象。 将 NSMenu 实例连接到 NSTextView 的menu
出口。
将 IBAction 连接到 NSMenu 内的 NSMenuItem。
到目前为止一切顺利。一切都按预期工作:出现菜单项,并在选择它时调用该操作。
我需要在菜单出现之前从 NSTextView 获取选定的文本,以便我可以适当地配置我的菜单项。根据文档
如果您需要自定义上下文菜单,您可以通过设置 一个适当的对象作为菜单的委托并实现 menuWillOpen:根据您之前认为合适的方式自定义菜单的方法 它出现了。
我将 NSMenu 的代表连接到文件的所有者。没有调用任何委托方法。 (menuWillOpen:
是我唯一需要的,但我也尝试过其他的)。
我在选择菜单项时调用的 IBAction 内设置了一个断点。如果我使用调试器检查菜单,我可以看到委托已正确设置为实现委托方法的对象。
还有什么要检查的吗?我做错了什么?
Xcode v4.6.3 SDK v10.8 部署目标 10.7
【问题讨论】:
【参考方案1】:经过一番挖掘,我发现:NSTextView
构建了一个不同的 NSMenu
实例以用作上下文菜单,可能是通过覆盖 -menuForEvent:
或一些类似的内部方法。这个新菜单从您在 Interface Builder 中创建的菜单中复制菜单项(实际上,它创建了新的菜单项实例,其属性是从原始菜单项中复制的),但它不复制菜单委托,这就是您的菜单委托的原因没有收到-menuWillOpen:
。我不确定这是否是故意的。阅读您发布的文档引用,这似乎是一个错误。
您可以做的是将您的NSTextView
实例的委托设置为类符合NSTextViewDelegate
的对象(可能是您的文件所有者,它已经符合NSMenuDelegate
)并实现以下方法:
- (NSMenu *)textView:(NSTextView *)view menu:(NSMenu *)menu forEvent:(NSEvent *)event atIndex:(NSUInteger)charIndex
// if the menu delegate is not self, set another object
[menu setDelegate:self];
return menu;
这将确保文本视图创建的上下文菜单使用您的委托。
注意:由于NSTextView
创建了一个不同的上下文菜单,它可能可能希望将菜单委托设置为它自己或其他一些内部对象。在我的测试中,委托是nil
,所以看起来它是安全的。或者,您可以丢弃建议的 menu
参数并返回您自己的 NSMenu
实例,并正确设置委托。
【讨论】:
太棒了!按照您的建议设置代表似乎可行,但我什至不必这样做。您指出的 NSTextViewDelegate 调用使我可以访问文本视图和菜单,这是我根据需要自定义菜单所需的一切。非常感谢。【参考方案2】:找到这个帖子为我节省了很多时间...谢谢!这是一个在 Swift 中的 NSView
中工作的实现。 myNSMenu
是 Storyboard 到 appDelegate
的出口,也是 NSMenu
的子类。如果没有在下面的代码中分配委托,NSMenuDelegate
函数不会被调用。
let appDelegate = NSApplication.sharedApplication().delegate as! AppDelegate
appDelegate.myNSMenu.delegate = appDelegate.myNSMenu
NSMenu.popUpContextMenu(appDelegate.myNSMenu, withEvent: theEvent, forView: self)
【讨论】:
以上是关于上下文菜单不调用 NSMenuDelegate 方法的主要内容,如果未能解决你的问题,请参考以下文章