Dru*_*erB 5 cocoa multithreading objective-c nsmenu appkit
显示上下文NSMenu. 我提出了自己的菜单,不使用menu的特性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.");
Run Code Online (Sandbox Code Playgroud)
在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];
});
Run Code Online (Sandbox Code Playgroud)
我不认为你要求的是可能的,但是,你可以做一些看起来非常相似的事情:
1)使用 NSPopover 而不是菜单。这是异步的,旨在用于可以使用弹出菜单的许多上下文中。如果您需要支持没有弹出窗口的操作系统版本,您也可以随时创建一个带有按钮的 NSWindow。
2) 如果您尝试运行计时器或在运行循环上安排的其他操作(例如下载),您可以在 NSEventTrackingRunLoopMode 中安排这些操作。默认情况下,它们仅计划为 NSDefaultRunLoopMode (这是有道理的,因为您不想在计时器触发显示警报时取消用户的菜单选择)。
老实说,你想做的事情似乎有点毫无意义、令人困惑、倒退和滥用菜单。但这可能只是因为我不知道你想要实现什么目标。你的高级任务是什么?为什么当菜单打开时需要在主线程上发生什么?你不能让其他事情(在你的例子中是 NSLog() )发生在第二个线程上并将菜单留在主线程上吗?
| 归档时间: |
|
| 查看次数: |
1662 次 |
| 最近记录: |