Swift macOS菜单栏应用程序:未显示主菜单

Swift macOS菜单栏应用程序:未显示主菜单,swift,macos,cocoa,background-process,menubar,Swift,Macos,Cocoa,Background Process,Menubar,我有一个状态栏应用程序,它在菜单栏中运行。因此,我在info.plst中将Application is agent(UIElement)设置为true。这导致我的应用程序没有停靠图标和菜单栏 但是,我还有一个用户可以从statusbar菜单打开的首选项窗口。下面是我打开它的方式: if (!NSApp.setActivationPolicy(.regular)) { print("unable to set regular activation policy") } NSApp.acti

我有一个状态栏应用程序,它在菜单栏中运行。因此,我在
info.plst
中将
Application is agent(UIElement)
设置为
true
。这导致我的应用程序没有停靠图标和菜单栏

但是,我还有一个用户可以从statusbar菜单打开的首选项窗口。下面是我打开它的方式:

if (!NSApp.setActivationPolicy(.regular)) {
    print("unable to set regular activation policy")
}
NSApp.activate(ignoringOtherApps: true)
if let window = preferencesWindowController.window {
    window.makeKeyAndOrderFront(nil)
}

窗口按预期显示,但应用程序的主菜单栏(包含文件、编辑等)不显示。只有当我单击另一个应用程序并返回到我的应用程序时,才会显示菜单栏

我注意到,如果我将
info.plst
中的值更改为
false
,并在
applicationdFinishLaunching()
中使用
NSApp.setActivationPolicy(.association)
,则结果相同。但是,如果在调用
applicationdFinishLaunching()
几毫秒后,我使用计时器调用
NSApp.setActivationPolicy(.accessority)
,它将正常工作,主菜单将按预期显示。然而,这样做的副作用是,应用程序图标会在dock中弹出几秒钟(直到计时器被触发),这不是一个好的用户体验

有人知道我还能尝试什么吗?当我切换活动应用程序时,代码中没有执行的操作会发生什么

我正在macOS 10.12.2(16C67)上使用版本8.2.1(8C1002)


谢谢

这是我目前的解决方案:

正如我在问题中所写的,如果我点击另一个应用程序并返回到我的应用程序,菜单栏就会显示出来。当我尝试显示首选项窗口时,我正在模拟此操作:

    NSApp.setActivationPolicy(.regular)
    NSApp.activate(ignoringOtherApps: true)
    window.makeKeyAndOrderFront(nil)

   if (NSRunningApplication.runningApplications(withBundleIdentifier: "com.apple.dock").first?.activate(options: []))! {
       let deadlineTime = DispatchTime.now() + .milliseconds(200)
       DispatchQueue.main.asyncAfter(deadline: deadlineTime) {                 
       NSApp.setActivationPolicy(.regular)
            NSApp.activate(ignoringOtherApps: true)
       }
   }

这不是一个完美的解决方案。如果我找不到更好的解决方案,我将提交一个bug。

我尝试了apple脚本,它看起来像预期的那样工作

除此之外,在通过按键关闭然后重新打开新窗口(短时间间隔)后,菜单将保持选中状态

GIF演示:

基于OP的修复(或解决方法)。关键是切换到焦点(谢谢@Daniel!)

一些小的改进:

无需强制展开,无需设置ActivationPolicy并调用activate两次

NSApp.setActivationPolicy(.regular)
window.makeKeyAndOrderFront(nil)    

NSRunningApplication.runningApplications(withBundleIdentifier: "com.apple.dock").first?.activate(options: [])

OperationQueue.current?.underlyingQueue?.asyncAfter(deadline: .now() + .milliseconds(200), execute: {
    NSApp.activate(ignoringOtherApps: true)
})

我可能会为此找到另一个解决方案(这在macOS 10.15上仍然是一个问题)。我发现了一个类似的问题+解决方案。idea将显示和隐藏当前应用程序的菜单栏。我需要运行它两个不同的运行循环,但它工作。以下是解决方案:

OperationQueue.main.addOperation{
NSMenu.setmenubavisible(false)
OperationQueue.main.addOperation{
NSMenu.setmenubavisible(true)
}
}

我找到了另一种解决方案,它不需要对dock和back进行调焦,在应用程序退出/进入focus时会引起闪烁。 这将在下一个勾选中将激活策略设置为禁止,然后设置为常规:

如果NSApp.activationPolicy()!=。正规的{
NSApp.setActivationPolicy(.违禁)
DispatchQueue.main.asyncAfter(截止日期:DispatchTime.now()+毫秒(200)){
NSApp.setActivationPolicy(.regular)
NSApp.activate(忽略其他应用程序:true)
车窗。MakeKeyandDerfront(无)
}
}否则{
//激活策略已经正常,只需正常打开窗口即可
NSApp.activate(忽略其他应用程序:true)
车窗。MakeKeyandDerfront(无)
}

“窗口按预期显示”我假设该窗口也会成为第一响应者,看起来不像是背景或其他东西。对吗?我的应用程序也遇到了这个问题。你并不孤单:)我也有同样的问题,我还没有找到有效的解决方案。您在哪里运行上述代码?在AppDelegate的ApplicationIDFinishLaunching函数中?您好!你有没有找到更好的解决办法?没有。对不起,谢谢你的回答。注意:苹果的脚本在Mac应用商店上不起作用。我认为如果你的应用程序是沙盒的话,它根本不起作用。谢谢你的建议。不幸的是,菜单栏出现了,但单击菜单栏上的项目不起作用。我用它修复了一个问题,该问题锁定了与菜单栏的交互,当我使用应用程序的图标(保持在dock中)重新打开以前隐藏的应用程序窗口以进入statusbar应用程序状态时会发生这种情况
NSApp.setActivationPolicy(.regular)
window.makeKeyAndOrderFront(nil)    

NSRunningApplication.runningApplications(withBundleIdentifier: "com.apple.dock").first?.activate(options: [])

OperationQueue.current?.underlyingQueue?.asyncAfter(deadline: .now() + .milliseconds(200), execute: {
    NSApp.activate(ignoringOtherApps: true)
})