我正在构建一个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];
我认为问题可能与没有任何窗户带到前面有关。我觉得我在这里抓稻草。任何帮助将不胜感激。
答案 0 :(得分:2)
我认为问题在于当NSMenu
打开时runloop如何运作,因此您应该在显示菜单之前尝试激活应用程序。如果你有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];
}
这应该有效,但我认为虽然一般情况下你会有更好的运气而不是菜单。
答案 1 :(得分:1)
您可能需要允许输入-becomeFirstResponder
,或者通过覆盖-canBecomeFirstResponder
或自行调用“成为”方法。
您可能必须为任何容纳文本输入的视图实现/调用这些方法,或者可能告诉输入视图成为第一个响应者。
无论哪种方式,它都像回应链问题一样。
答案 2 :(得分:1)
尝试在窗口上调用-makeFirstResponder:
。 NSWindow通常是NSResponder链的起点。
- (void)menuWillOpen:(NSMenu *)menu {
[[NSApp mainWindow] makeFirstResponder:yourTextInputField];
}
我假设您的文字字段已经接受了第一响应者,因为您说您的应用最初是以第一响应者的身份启动的。如果没有,请确保您的文本字段覆盖-acceptsFirstResponder:
以返回YES
- (BOOL)acceptsFirstResponder {
return YES;
}
编辑:啊,看到你没有关键窗口。看起来NSMenu实际上有一个与之关联的窗口,调用-makeFirstResponder:
是安全的。有些讨论here建议在您的视图中覆盖-viewDidMoveToWindow:
,其中包含NSMenu中的文本字段,如下所示:
- (void)viewDidMoveToWindow {
[super viewDidMoveToWindow];
[[self window] makeFirstResponder:yourTextInputField];
}