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

Kis*_*ore 3 macos cocoa objective-c

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

我们是否有办法对应用程序进行编码,即使它已退出,应用程序也始终在菜单栏中进行重新设置.

谢谢.

ste*_*iva 6

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

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

我在这里留下代码,展示了如何加载和卸载由NSWindowController self.winconself作为应用程序委托对象控制的主GUI .它加载和控制一个单独的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;
}
Run Code Online (Sandbox Code Playgroud)

Notes已添加10/6/2016,因为这有一些牵引力:

这个问题有一个较旧的答案.它对变化的历史进行了很好的讨论,但缺乏示例代码.

最后,这个答案和问题完全没有LSUIElement关键字,这是此类应用程序的历史OSX plist设置.如上面的答案中所述和这个最近的问题,LSUIElement应该被视为已弃用.如果您发现了一篇旧博客文章,那么您希望找到更多最近的代码示例,建议不要使用它.