After some digging, this is what I found: NSTextView
builds a different NSMenu
instance to use as the contextual menu, probably by overriding -menuForEvent:
or some similar internal method. This new menu copies the menu items from the menu you created in Interface Builder (in fact, it creates new menu item instances whose attributes are copied from the original menu items) but it does not copy the menu delegate, which is why your menu delegate does not receive -menuWillOpen:
. I am not sure whether this is intentional or not. Reading that documentation quote you posted, it seems to be a bug.
What you can do is to set the delegate of your NSTextView
instance to an object whose class conforms to NSTextViewDelegate
(maybe your File’s Owner, which already conforms to NSMenuDelegate
) and implement the following method:
- (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;
}
This will make sure that the contextual menu created by the text view uses your delegate.
NB: since NSTextView
creates a different contextual menu, it could be the case that it might want to set the menu delegate to itself or some other internal object. In my tests the delegate is nil
, so it looks like it’s safe. Alternatively, you could discard the proposed menu
argument and return your own NSMenu
instance with the delegate correctly set.