显示上下文NSMenu而不阻塞主线程

时间:2013-04-21 13:43:21

标签: objective-c multithreading cocoa appkit nsmenu

在显示上下文NSMenu时,我有一些意想不到的结果。我自己展示菜单,而不是使用menu的{​​{1}}属性。事实证明,提出NSResponder是一种阻止操作。

在新模板项目中,我只在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

2 个答案:

答案 0 :(得分:2)

我不认为你的要求是可能的,但是,你可以做的一些看起来相似的东西:

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

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

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

答案 1 :(得分:-1)

  1. 立即显示菜单
  2. 在后台主题中准备菜单项
  3. 从主线程添加菜单项。
  4. 像这样:

    createScreenCapture()