[英]macOS menubar application: main menu not being displayed
我有一個狀態欄應用程序,它在菜單欄中運行。 因此,我在info.plst
中將Application is agent (UIElement)
為true
。 這導致我的應用程序沒有停靠圖標和菜單欄。
但是,我還有一個用戶可以從狀態欄菜單打開的首選項窗口。 這是我打開它的方法:
if (!NSApp.setActivationPolicy(.regular)) {
print("unable to set regular activation policy")
}
NSApp.activate(ignoringOtherApps: true)
if let window = preferencesWindowController.window {
window.makeKeyAndOrderFront(nil)
}
該窗口按預期顯示,但帶有File 、 Edit等的應用程序主菜單欄沒有顯示。 只有當我單擊另一個應用程序並返回到我的應用程序時,才會顯示菜單欄。
我注意到,如果我將info.plst
的值更改為false
並在applicationDidFinishLaunching()
使用NSApp.setActivationPolicy(.accessory)
applicationDidFinishLaunching()
,它具有相同的結果。 但是,如果我在applicationDidFinishLaunching()
被調用后幾毫秒用計時器調用NSApp.setActivationPolicy(.accessory)
,它會工作並且主菜單按預期顯示。 然而,這有一個副作用,即應用程序圖標會在 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)
}
}
這不是一個完美的解決方案。 如果我找不到更好的解決方案,我將提交一個錯誤。
基於 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)
})
我嘗試使用蘋果腳本,它似乎按預期工作。
除了通過按鍵關閉然后重新打開一個新窗口(短時間間隔)后,菜單將保持選中狀態。
if NSApp.activationPolicy() == .accessory {
NSApp.setActivationPolicy(.regular)
} else {
var errorDict: NSDictionary?
NSAppleScript(source: """
tell application "Dock" to activate current application
""")?.executeAndReturnError(&errorDict)
if errorDict != nil{
print(errorDict!)
// error executing apple script
NSApp.activate(ignoringOtherApps: true)
}
}
window?.makeKeyAndOrderFront(self)
GIF 演示:
我可能為此找到了另一個解決方案(這在 macOS 10.15 上仍然是一個問題)。 我在這里找到了類似的問題 + 解決方案。 這個想法即將顯示和隱藏當前應用程序的菜單欄。 我需要運行 2 個不同的運行循環,但它有效。 這是解決方案:
OperationQueue.main.addOperation {
NSMenu.setMenuBarVisible(false)
OperationQueue.main.addOperation {
NSMenu.setMenuBarVisible(true)
}
}
我找到了另一種解決方案,它不涉及將停靠欄聚焦和向后聚焦,這會導致應用程序退出/進入焦點時出現閃爍。 這將激活策略設置為禁止,然后在下一個滴答中常規:
if NSApp.activationPolicy() != .regular {
NSApp.setActivationPolicy(.prohibited)
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + .milliseconds(200)) {
NSApp.setActivationPolicy(.regular)
NSApp.activate(ignoringOtherApps: true)
window.makeKeyAndOrderFront(nil)
}
} else {
// activation policy was already regular, just do normal window opening
NSApp.activate(ignoringOtherApps: true)
window.makeKeyAndOrderFront(nil)
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.