菜单栏应用程序永远不会重新激活

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];

【讨论】:

以上是关于菜单栏应用程序永远不会重新激活的主要内容,如果未能解决你的问题,请参考以下文章

强制地址栏显示在移动 Chrome 应用中

菜单栏中的菜单项未激活,无法选择或单击

vue实战:路由监听

重新加载页面后如何突出显示导航栏中的活动菜单项

MFC单文档程序的菜单栏怎么修改高度和宽度?

如何在 Windows 中取消“系统键关闭”状态