簡體   English   中英

macOS 菜單欄應用程序:未顯示主菜單

[英]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)
}

該窗口按預期顯示,但帶有FileEdit等的應用程序主菜單欄沒有顯示。 只有當我單擊另一個應用程序並返回到我的應用程序時,才會顯示菜單欄。

我注意到,如果我將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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM