如何在菜单中显示应用程序图标甚至应用程序退出 [英] How to display application icon in menubar even application is quit
问题描述
我的应用程序在菜单栏中显示一个图标,但是当应用程序退出时,图标会从菜单栏中消失。
我们有办法
感谢。
您可以将应用程序切换到后台(附件)模式,然后再返回。语义上,应用程序从不退出。
基本思想是使用 NSApplicationDelegate
协议来回切换附件和常规应用程序模式。已经有方法来取消退出,捕获所有窗口关闭,并处理用户尝试启动您的应用程序,即使它仍然运行。所以把它放在一起,你得到下面的代码。
我离开代码在这里展示如何加载和卸载由 NSWindowController
self.wincon
其中self是应用程序委托对象。它加载并控制单独的 MainWindow.xib
。如果您没有主菜单以外的窗口,则可能不必要。
我还有一个用户首选项,需要设置为启用所有此行为。
我在 MainMenu.xib
中没有任何东西,但菜单 -
//帮助关闭主窗口并切换到附件模式
- (void)switchToBackgroundMode
{
@autoreleasepool {
//需要检查加载以防止关闭关闭的窗口和
//触发第二次调用applicationShouldTerminateAfterLastWindowClosed
if([self.wincon isWindowLoaded])[self.wincon close];
self.wincon = nil;
}
//隐藏菜单和dock图标
[NSApp setActivationPolicy:NSApplicationActivationPolicyAccessory];
}
#pragma mark应用程序委托方法
//使用CMD-Q调用
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
{
//取消终止if pref设置
if([MyPreferencesController runInBackground])
{
[self switchToBackgroundMode];
return NSTerminateCancel;
}
return NSTerminateNow;
}
//所有窗口关闭时调用
- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender
{
if([MYPreferencesController runInBackground] ){
//这个检查是必要的,以避免在退出时调用switchToBGmode两次
if(![NSApp activationPolicy] == NSApplicationActivationPolicyAccessory)
[self switchToBackgroundMode];
return NO;
} else {
return YES;
}
}
//如果应用程序处于附件模式,并且用户通过Dock或通过
//单击userNotification或尝试打开应用程序
- (BOOL)applicationShouldHandleReopen:(NSApplication *)sender hasVisibleWindows:(BOOL)flag
{
if(!self.wincon){
self.wincon = [MYMainWindowController alloc] initWithWindowNibName:@MainWindow];
}
//这确保dock图标返回
[NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
//显示窗口
[self.wincon showWindow:NSApp];
[self.wincon.window makeKeyAndOrderFront:NSApp];
return YES;
}
p>
有一个这个问题的旧答案。
最后,这个答案和问题完全缺少了 LSUIElement
关键字,这是一个历史OSX plist设置这种类型的应用程序。如上述答案和这个更新的问题, LSUIElement
应被视为已弃用 。如果你发现一个旧的博客文章提到它,希望你发现更多的最近的代码示例,建议不要使用它。
My application shows a icon in the menu bar but when the application is quit the icon goes off from the menu bar.
Do we have a way to code such that application always remian in the menu bar even it is quit.
Thanks.
You can definitely switch an app to background (Accessory) mode and back again. Semantically, the application never quits.
The basic idea is to use the NSApplicationDelegate
protocol to switch back and forth between accessory and regular app modes. There are already methods to cancel quit, catch all windows being closed, and to handle the user trying to launch your app even if it's still running. So put it all together, and you get the code below.
I left in code here showing how to load and unload the main GUI controlled by the NSWindowController
self.wincon
where self is the application delegate object. It loads and controls a separate MainWindow.xib
. If you don't have a window other than the mainmenu, it might be unnecessary.
I also have a user preference that needs to be set to enable all of this behavior. By default, it will really, really quit.
I have nothing in MainMenu.xib
but the menu-- switching to accessory mode will mean the menu is not displayed.
// Helper to close main window and switch to accessory mode
- (void) switchToBackgroundMode
{
@autoreleasepool {
// Need to check loaded to prevent closing a closed window and
// triggering a second call to applicationShouldTerminateAfterLastWindowClosed
if ([self.wincon isWindowLoaded]) [self.wincon close];
self.wincon = nil;
}
// Hide the menu and dock icon
[NSApp setActivationPolicy:NSApplicationActivationPolicyAccessory];
}
#pragma mark Application Delegate Methods
// Called with a CMD-Q
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
{
// Cancel terminate if pref set
if ([MyPreferencesController runInBackground])
{
[self switchToBackgroundMode];
return NSTerminateCancel;
}
return NSTerminateNow;
}
// Called when all windows closed
- (BOOL) applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender
{
if ([MYPreferencesController runInBackground]) {
// This check is necessary to avoid calling switchToBGmode twice on a quit
if (![NSApp activationPolicy] == NSApplicationActivationPolicyAccessory)
[self switchToBackgroundMode];
return NO;
} else {
return YES;
}
}
// Called if the app is in accessory mode and the user activates it through the dock or by
// clicking a userNotification or trying to open the app
- (BOOL) applicationShouldHandleReopen:(NSApplication *)sender hasVisibleWindows:(BOOL)flag
{
if (!self.wincon) {
self.wincon = [[MYMainWindowController alloc] initWithWindowNibName:@"MainWindow"];
}
// This ensures that the dock icon comes back
[NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
// Show the window
[self.wincon showWindow:NSApp];
[self.wincon.window makeKeyAndOrderFront:NSApp];
return YES;
}
Notes added 10/6/2016 since this has gotten some traction:
There is an older answer to this question. It has a good discussion of the history of the changes but lacks sample code.
Finally, this answer and question entirely lacked the LSUIElement
keyword, which was a historical OSX plist setting for apps of this type. As described in the answer above and this more recent question, LSUIElement
should be considered deprecated. If you have found an old blog post mentioning it, hopefully you have found more recent code samples that recommend not using it at all.
这篇关于如何在菜单中显示应用程序图标甚至应用程序退出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!