I am building my first macOs app in Swift. I have managed to add a menu (NSMenu) to the Menu Bar Extra icon, but when the menu loads each menu item is shown as deactivated. I understand this is automatic behaviour when the app can't find a #selector for a menu item.
But the thing is I do have a selector for each menu item. If I place the method declarations for those selectors in the AppDelegate then the menu sees them fine and shows the menu items as activated. But if I place then in a dedicated MenuManager
class, then it seems to not see them at all and sets the menu items as deactivated. Note, weirdly, the compiler is seeing them fine. if it didn't it would show a compiler error. But at runtime the menu seems to not be able to find those methods unless they are in the AppDelegate.
Here is how I am declaring the menu item (in a class called BarIconMenu which subclasses NSMenu)
let short = NSMenuItem(
title: "Short (20 words)",
action: #selector(MenuManager.copyShortSnippetToClipboard),
keyEquivalent: ""
)
And here is how that method is defined in the MenuManager class
@objc func copyShortSnippetToClipboard() {
clipboardManager.copyText(withLength: .short)
ProgressHUD.showSuccessWithStatus("Copied to clipboard")
}
I have tried everying I can think of, including 1) cleaning the build, 2) appending @objc
in front of the MenuManager
class, 3) initialising the menu in MenuManager instead of the AppDelegate - but nothing is working.
I don't want all my code to live in the AppDelegate, so how can I get my menu item selectors to 'see' the methods I need them to call?
The init method sets a few properties as a convenience, but the NSMenuItem class has several others. An action selector will set the method to be called, but the target is the object the message is actually sent to, so you can just set the menuItem's target as desired (otherwise the AppDelegate usually winds up as the default).