当所选函数移至其他class时,NSMENUITEM带有添加到NSSTATUSBAR中的动作呈灰色。

NSMenuItem with action added to NSStatusBar is grayed out when the selected function is moved to other class

如果作为 NSMenuItem 操作调用的函数不在 AppDelegate 中,菜单条目将显示为灰色。

我似乎无法弄清楚到底哪里出了问题...也许我在初始化 StatusBarItemController 时出错了?只要我将 printToTheWalls 移动到 AppDelegate class,它就会开始工作。

import Cocoa

@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
    var statusBarItemController: StatusBarItemController?
    let statusBarItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.squareLength)

    func applicationDidFinishLaunching(_ aNotification: Notification) {
        // Insert code here to initialize your application
        statusBarItemController = StatusBarItemController()
        if let button = statusBarItem.button {
            button.image = NSImage(named: NSImage.Name("trayIcon"))
        }
        statusBarItemController?.constructMenu(with: statusBarItem)
    }

    func applicationWillTerminate(_ aNotification: Notification) {
        // Insert code here to tear down your application
    }

}
import Cocoa

class StatusBarItemController {

    func constructMenu(with statusBarItem: NSStatusItem) {
        let menu = NSMenu()
        menu.addItem(NSMenuItem(
            title: "From the windows...",
            action: #selector(printToTheWalls(_:)),
            keyEquivalent: ""
        ))
        menu.addItem(NSMenuItem.separator())
        menu.addItem(NSMenuItem(
            title: "Quit",
            action: #selector(NSApplication.terminate(_:)),
            keyEquivalent: "q"
        ))

        statusBarItem.menu = menu
    }

    @objc func printToTheWalls(_ sender: NSMenuItem) {
        //This doesn't seem to be called and/or found
        print("To the Walls!")
    }
}

解决方案是手动将目标 属性 设置为 self 因为 @vadian 和 @red_menace 帮助我在问题的评论中发现。

工作代码如下所示:

import Cocoa

@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
    var statusBarItemController: StatusBarItemController?

    func applicationDidFinishLaunching(_ aNotification: Notification) {
        // Insert code here to initialize your application
        statusBarItemController = StatusBarItemController()
    }

    func applicationWillTerminate(_ aNotification: Notification) {
        // Insert code here to tear down your application
    }

}
import Cocoa

class StatusBarItemController: NSObject {
    let statusBarItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.squareLength)

    override init() {
        super.init()
        if let button = statusBarItem.button {
            button.image = NSImage(named: NSImage.Name("trayIcon"))
        }
        constructMenu()
    }

    func constructMenu() {
        if let button = statusBarItem.button {
            button.image = NSImage(named: NSImage.Name("trayIcon"))
        }
        let menu = NSMenu()

        let fromTheWindowsItem = NSMenuItem(
            title: "From the windows...",
            action: #selector(StatusBarItemController.printToTheWalls(_:)),
            keyEquivalent: ""
        )
        fromTheWindowsItem.target = self
        menu.addItem(fromTheWindowsItem)
        menu.addItem(NSMenuItem.separator())
        menu.addItem(NSMenuItem(
            title: "Quit",
            action: #selector(NSApplication.terminate(_:)),
            keyEquivalent: "q"
        ))

        statusBarItem.menu = menu
    }

    @objc func printToTheWalls(_ sender: NSMenuItem) {
        print("To the Walls!")
    }
}