从 `main()` 创建的 `NSStatusItem` 没有显示在系统状态栏上

`NSStatusItem` created from `main()` doesn't show up on system status bar

我正在尝试制作一个简单的 macOS Cocoa 应用程序,使用 NSStatusItem 在系统状态栏上创建一个可点击的图标。但是,当我启动我的应用程序时,我收到此警告并且图标没有显示:

2020-03-03 14:43:11.564 Mocha_bug_example[936:39572] CGSGetActiveMenuBarDrawingStyle((CGSConnectionID)[NSApp contextID], &sCachedMenuBarDrawingStyle) returned error 268435459 on line 46 in NSStatusBarMenuBarDrawingStyle _NSStatusBarGetCachedMenuBarDrawingStyle(void)

这是我的应用程序的最小可重现示例:

#import <AppKit/AppKit.h>

NSStatusItem* statusItem;

int main (int argc, char* argv[]) {
        statusItem = [NSStatusBar.systemStatusBar statusItemWithLength: -1];
        statusItem.button.title = @"foobar";
        statusItem.visible = YES;

        [NSApplication.sharedApplication run];
        return 0;
}

我编译 运行 示例如下:

MacBook-Air-5:Mocha ericreed$ clang -o Mocha_bug_example -framework AppKit -fobjc-arc Mocha_bug_example.m
MacBook-Air-5:Mocha ericreed$ ./Mocha_bug_example
2020-03-03 14:43:11.564 Mocha_bug_example[936:39572] CGSGetActiveMenuBarDrawingStyle((CGSConnectionID)[NSApp contextID], &sCachedMenuBarDrawingStyle) returned error 268435459 on line 46 in NSStatusBarMenuBarDrawingStyle _NSStatusBarGetCachedMenuBarDrawingStyle(void)
[Application hung until I pressed Ctrl+C]
^C
MacBook-Air-5:Mocha ericreed$ 

注意:按照 this similar question 的建议,在调用 run 后禁用自动引用计数并添加 [statusItem release]; 没有明显的区别。

这不是你在 main() 可以做的事情。

除了极度异常情况,千万不要修改应用模板自带的main(),必须调用NSApplicationMain():

int main(int argc, char *argv[])
{
    // start the application
    return NSApplicationMain(argc, (const char **) argv);
}

Cocoa 框架在您调用 NSApplicationMain() 之前不会被初始化,并且通常在此之前无法使用。

这种设置应该在applicationWillFinishLaunchingapplicationDidFinishLaunching中完成。

更新

楼主使用Xcode愿意独自闯荡荒野。 ;)

这也意味着他们的应用程序包将没有主 NIB 文件,该文件通常会创建和连接应用程序委托对象、主菜单等。

有些勇敢的人曾勇敢地闯过这片土地,您可以在 Creating a Cocoa application without NIB files 中读到。

#import <Cocoa/Cocoa.h>

int main(){
 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];
 NSApplication *application = [NSApplication sharedApplication];
 NSStatusItem* statusItem;
 statusItem = [NSStatusBar.systemStatusBar statusItemWithLength: -1];
 statusItem.button.title = @"foobar";
 statusItem.visible = YES;
 [application run];
 [pool drain];
 return 0;
}

使用名称 'statusBar_SO.m'

保存文件

从终端编译: clang statusBar_SO.m -framework Cocoa -o statusBar && ./statusBar

这是将状态栏项添加到命令行应用程序的方法mac osx cocoa

改编猿科对 Swift 的回答。只需将其放入 main.swift 文件:

let app = NSApplication()
let statusItem = NSStatusBar.system.statusItem(withLength: -1)
statusItem.button!.title = "PENIS!"
app.run()

我不明白 NSReleasePool 的更详细信息,因为它包含了 apodidae,但没有它它对我有用。