I had some unexpected results when displaying a contextual NSMenu
. I'm presenting the menu myself, not using the menu
property of an NSResponder
. It turned out, presenting an NSMenu
is a blocking operation.
In a new template project I only added the following code in applicationDidLaunch:
NSMenu *menu = [[NSMenu alloc] initWithTitle:@"Menu"];
[menu addItemWithTitle:@"Item 1" action:@selector(selected:) keyEquivalent:@""];
[menu addItemWithTitle:@"Item 2" action:@selector(selected:) keyEquivalent:@""];
[menu addItemWithTitle:@"Item 3" action:@selector(selected:) keyEquivalent:@""];
[menu popUpMenuPositioningItem:[menu itemAtIndex:0]
atLocation:CGPointMake(500, 500)
inView:nil];
NSLog(@"Context menu shown.");
The popUpMenuPositioningItem:atLocation:inView:
call doesn't return until I select an item or click outside to automatically dismiss the menu. The log is only printed once the menu is closed.
Why does this happen? And how can I prevent it? I found a couple of mentions of this problem, but the "solutions" always consisted of executing the other things in the background, instead of preventing NSMenu
from blocking.
EDIT:
If I present the menu in a background thread, the menu becomes unresponsive, doesn't react to clicks inside or outside.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
[[menu popUpMenuPositioningItem:[menu itemAtIndex:0]
atLocation:CGPointMake(500, 500)
inView:nil];
});