如何在菜单栏中显示应用程序图标甚至应用程序退出

时间:2014-06-06 19:01:50

标签: objective-c macos cocoa

我的应用程序在菜单栏中显示一个图标但是当应用程序退出时,图标会从菜单栏中消失。

我们是否有办法对代码进行编码,即使退出,应用程序也会在菜单栏中进行重新设置。

感谢。

1 个答案:

答案 0 :(得分:5)

你绝对可以将应用程序切换到后台(附件)模式,然后再返回。从语义上讲,应用程序永远不会退出。

基本思想是使用NSApplicationDelegate协议在附件和常规应用模式之间来回切换。已有方法取消退出,捕获所有关闭的窗口,并处理尝试启动应用程序的用户,即使它仍在运行。所以把它们放在一起,你得到下面的代码。

我在这里留下代码,展示了如何加载和卸载由NSWindowController self.wincon控制的主GUI,其中self是应用程序委托对象。它加载并控制单独的MainWindow.xib。如果您没有主菜单以外的窗口,则可能没有必要。

我还有一个用户首选项需要设置为启用所有这些行为。默认情况下,它真的会真的退出。

MainMenu.xib中没有任何内容,但菜单 - 切换到附件模式意味着菜单不会显示。

// 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添加了10/6/2016,因为这有一些牵引力:

有一个older answer to this question。它对变化的历史进行了很好的讨论,但缺乏示例代码。

最后,这个答案和问题完全缺少LSUIElement关键字,这是此类应用程序的历史OSX plist设置。如上面的答案和this more recent question所述, LSUIElement应被视为已弃用 。如果您发现了一篇提及它的旧博客文章,希望您找到了最近的代码示例,建议您不要使用它。