【问题标题】:Display contextual NSMenu without blocking main thread在不阻塞主线程的情况下显示上下文 NSMenu
【发布时间】:2013-04-21 13:43:20
【问题描述】:

在显示上下文 NSMenu 时,我得到了一些意想不到的结果。我自己呈现菜单,而不是使用NSRespondermenu 属性。事实证明,呈现NSMenu 是一种阻塞操作。

在一个新的模板项目中,我只在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.");

popUpMenuPositioningItem:atLocation:inView: 调用不会返回,直到我选择一个项目或在外部单击以自动关闭菜单。只有在菜单关闭后才会打印日志。

为什么会这样?我该如何预防呢?我发现有几个提到这个问题,但“解决方案”总是包括在后台执行其他事情,而不是阻止 NSMenu 阻塞。

编辑:

如果我在后台线程中显示菜单,菜单会变得无响应,不会对内部或外部的点击做出反应。

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
    [[menu popUpMenuPositioningItem:[menu itemAtIndex:0] 
                         atLocation:CGPointMake(500, 500) 
                             inView:nil];
});

【问题讨论】:

  • 你能提供更多的上下文吗?菜单打开时你想做什么而你现在不能?

标签: objective-c multithreading cocoa appkit nsmenu


【解决方案1】:

我认为您的要求是不可能的,但是,您可以做一些看起来非常相似的事情:

1) 使用 NSPopover 代替菜单。这是异步的,旨在用于可以使用弹出菜单的许多上下文中。如果您需要支持没有弹出框的操作系统版本,您也可以随时创建一个带有按钮的 NSWindow。

2) 如果您尝试运行计时器,或在运行循环中安排的其他操作(例如下载),您可以在 NSEventTrackingRunLoopMode 中安排这些操作。默认情况下,它们仅被安排在 NSDefaultRunLoopMode(这是有道理的,因为当计时器触发显示警报时,您不想取消用户的菜单选择)。

说实话,您尝试做的事情似乎有点毫无意义、令人困惑、倒退和滥用菜单。但这可能只是因为我不知道你想要达到什么目的。你的高级任务是什么?为什么菜单启动时主线程上需要发生什么。您不能在第二个线程上发生 other 事情(在您的示例中为 NSLog())并将菜单留在主线程上吗?

【讨论】:

  • 如果我想重绘一个视图怎么办? drawRect: 不是在主线程上调用的吗?
  • 要显示视图,请在视图/窗口上调用 -display。如果你在非主线程上,你可以使用 performSelectorOnMainThread:withObject:waitUntilDone:modes:,确保传入 NSEventTrackingRunLoopMode,而不仅仅是默认的运行循环模式。该队列由主运行循环检查,这意味着它由菜单运行的事件处理代码触发,以确定您是否选择了菜单项或移动了鼠标。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多