菜单栏应用程序永远不会重新激活
Posted
技术标签:
【中文标题】菜单栏应用程序永远不会重新激活【英文标题】:Menu Bar App Never Becomes Reactivated 【发布时间】:2013-02-28 03:44:59 【问题描述】:我正在构建一个 Mac 应用程序,它只位于菜单栏中,没有停靠项,没有键窗口,也没有主菜单(info.plist 中的 LSUIElement
设置为 YES
)。当我第一次启动应用程序时,applicationDidBecomeActive:
被调用,正如我所料。但是,一旦另一个应用程序获得焦点,applicationDidBecomeActive:
就再也不会被调用。
这可以防止我的应用程序中的文本字段成为第一响应者。当我第一次打开应用程序时,文本字段是可编辑的:
但是在另一个应用程序来到前台后,文本字段不可编辑:
我尝试过的:
当菜单打开时,menuWillOpen:
被 NSMenu
的委托调用。我试过放置以下内容但没有成功:
[NSApp unhide];
[NSApp arrangeInFront:self];
[NSApp activateIgnoringOtherApps:YES];
[NSApp requestUserAttention:NSCriticalRequest];
[[NSRunningApplication currentApplication] activateWithOptions:NSApplicationActivateIgnoringOtherApps];
[[NSRunningApplication currentApplication] unhide];
我认为这个问题可能与没有任何窗户可以放在前面有关。我觉得我在这里抓住了稻草。任何帮助将不胜感激。
【问题讨论】:
如果应用程序从未重新启动,为什么还要再次调用它。如果它在菜单栏中,它的进程不是作为一种准守护进程存在吗? 也许它没有任何关系,但我最近遇到了一个问题,ios 没有在恢复事件之后将视图作为第一响应者(当它是恢复之前的第一响应者时)。解决方法是在发送 becomeFirstResponder 消息之前 resignFirstResponder。不知道为什么,但它得到了 iOS 的支持。也许这里有类似的东西在起作用? 嘿,Ash,问题可能与 NSMenu 有关。将它用于文本输入从来都不是一个好主意。您是否尝试过使用 NSWindow 的相同步骤? 【参考方案1】:我认为问题在于打开NSMenu
时运行循环的运行方式,因此您应该在显示菜单之前尝试激活应用程序。如果您有 NSStatusItem
显示它,我建议您自己这样做:
- (void)toggleMenu:(id)sender
// App might already be active
if ([NSApp isActive])
[self.statusItem popUpStatusItemMenu:self.menu];
else
[NSApp activateIgnoringOtherApps:YES];
- (void)applicationDidBecomeActive:(NSNotification *)notification
[self.statusItem popUpStatusItemMenu:self.menu];
这应该可行,但我认为一般来说,使用实际窗口而不是菜单会更好。
【讨论】:
【参考方案2】:您可能需要允许对-becomeFirstResponder
的输入,可能通过覆盖-canBecomeFirstResponder
或自己调用 become 方法。
您可能必须为任何包含您的文本输入的视图实现/调用这些方法,或者可能告诉您的输入视图成为第一响应者。
无论哪种方式,它都像是一个响应链问题。
【讨论】:
【参考方案3】:尝试在您的窗口上调用-makeFirstResponder:
。 NSWindow 通常是 NSResponder 链的开始。
- (void)menuWillOpen:(NSMenu *)menu
[[NSApp mainWindow] makeFirstResponder:yourTextInputField];
我假设您的文本字段已经接受了第一响应者,因为您说您的应用最初以它作为第一响应者启动。如果没有,请确保您的文本字段覆盖 -acceptsFirstResponder:
以返回 YES
- (BOOL)acceptsFirstResponder
return YES;
编辑:啊,看到你没有关键窗口。看起来 NSMenu 实际上有一个与之关联的窗口,调用-makeFirstResponder:
是安全的。一些讨论 here 建议在包含 NSMenu 中的文本字段的视图上覆盖 -viewDidMoveToWindow:
,如下所示:
- (void)viewDidMoveToWindow
[super viewDidMoveToWindow];
[[self window] makeFirstResponder:yourTextInputField];
【讨论】:
以上是关于菜单栏应用程序永远不会重新激活的主要内容,如果未能解决你的问题,请参考以下文章