我使用Cocoa绑定来控制我的应用程序中按钮和菜单项的启用和禁用,一般来说它工作得非常好。但是,有一个问题:在菜单跟踪期间启用不会更新。
我的应用程序运行一项由用户启动的长任务。该任务在后台运行,因此一旦任务启动,控制就会返回到运行循环。用户可以在任务进行时做其他事情;但是,有些事情是用户在任务运行时无法做到的事情,以及用户只有在任务运行时才能做的事情。我希望在任务运行时禁用/启用与此类事物相关的菜单项和按钮,并在任务完成时相应地启用/禁用。
总的来说这很有效;我把它全部搞定了。唯一的问题是,如果用户在任务完成的时间点通过菜单栏进行跟踪,则菜单项不会更改其启用,直到用户停止跟踪为止。这意味着用户实际上可以选择一个应该被禁用的菜单项,因为菜单项的启用状态尚未更新。
所以我只需要一个我可以在我的任务完成时调用的调用,触发立即重新评估基于绑定的启用状态。有办法吗?
(注意这与多线程无关。该任务实际上是使用延迟执行请求在主线程上执行的(由于各种原因)。因此任务在主线程执行这样的运行循环期间完成,设置&# 34;立即完成"属性,然后返回,允许菜单跟踪继续。问题是AppKit在菜单跟踪期间显然没有做任何事情。)
更新 正如下面的评论中所解释的那样,我是个白痴。我已经切换到使用validateMenuItem:为我的菜单项启用,然后忘了我已经这样做了。所以问题是真的,但它是关于validateMenuItem:,而不是绑定。无论如何,对于任何发现这篇文章但实际上想知道如何强制菜单栏重新更新的人,快速回答是 - [NSMenu更新],我得到的答案很长:
- (void)forceImmediateMenuUpdate
{
// So, the situation is that the simulation has stopped playing because the end of the simulation was reached. If that happens while the user
// is tracking a menu in the menu bar, the menus do not get updating (enabling, titles) until the user ends menu tracking. This is sort of a
// bug in Cocoa, I guess; it assumes that state that influences menu bar items does not change while the user is tracking menus, which is false
// in our case, but is true for most applications, I suppose, maybe. Anyway, we need to force an immediate update in this situation.
NSMenu *mainMenu = [[NSApplication sharedApplication] mainMenu];
NSInteger numberOfSubmenus = [mainMenu numberOfItems];
for (int itemIndex = 0; itemIndex < numberOfSubmenus; ++itemIndex)
{
NSMenuItem *menuItem = [mainMenu itemAtIndex:itemIndex];
NSMenu *submenu = [menuItem submenu];
[submenu update];
}
}
我在我的任务完成时调用该方法,并且即使用户正在跟踪它们,菜单也会自行更新。 (这显然是一件值得怀疑的事情,但这里只是启用/禁用项目,而不是在用户的鼠标下拖拽它们: - &gt;)
我希望这有助于某人。对不起噪音。