cheesey
cheesey

Reputation: 516

NSMenu and NSStatusItem action wont work together

The button attached to NSStatusItem is not sending calls to its target selector.

I'm not sure what exactly I am doing wrong. I believe its something to do with the button.action line.

let statusItem = NSStatusBar.system.statusItem(withLength:NSStatusItem.squareLength)
let popover = NSPopover()

func applicationDidFinishLaunching(_ aNotification: Notification) {
    if let button = statusItem.button{
        button.image = NSImage(named:NSImage.Name("StatusBar"))
        button.action = #selector(someAction(_:)) //need help here

    }
    popover.contentViewController = QuotesViewController.freshController()
    constructMenu();

}

@objc func someAction(_ sender: Any?){
    print("working");
}

i was following this tutorial - raywenderlich

Edit

This process of setting actions workes for all of the NSMenuItems that I have. I just still the issue with the NSStatusItem.

Edit 2

The code displayed I believe is correct, I now think there's another problem somewhere else.

Edit 3 Answer

"If the status item has a menu set, the action is not sent to the target when the status item is clicked; instead, the click causes the menu to appear."- appledev NSStatusItem.action

Upvotes: 2

Views: 806

Answers (2)

William Gustafson
William Gustafson

Reputation: 548

You can dynamically assign and show the menu property to the button as needed. You'll need to implement the NSMenu menuDidClose method

self.statusItem = [[NSStatusBar systemStatusBar] statusItemWithLength: NSVariableStatusItemLength];
[self.statusItem.button sendActionOn: (NSLeftMouseUpMask|NSRightMouseUpMask)];
[self.statusItem.button setAction: @selector(statusItemClicked:)];

-(IBAction) statusItemClicked: (id) sender
{
    NSEvent *currentEvent = [NSApp currentEvent];

    // Right click conditions
    if  ((([currentEvent modifierFlags] & NSControlKeyMask) == NSControlKeyMask) ||
        (([currentEvent modifierFlags] & NSCommandKeyMask) == NSCommandKeyMask) ||
        (([currentEvent modifierFlags] & NSRightMouseUpMask) == NSRightMouseUpMask) ||    
        (([currentEvent modifierFlags] & NSRightMouseDownMask) == NSRightMouseDownMask) ||
        ([currentEvent type] == NSRightMouseDown) ||
        ([currentEvent type] == NSRightMouseUp))
    {
        [self showStatusMenu: self];
    }
    else
    {
        // do something besides showing the menu    
    }    
}

-(IBAction) showStatusMenu: (id) sender
{
    self.statusItem.menu = self.statusMenu;
    [self.statusItem.button performClick:nil];
}


-(void) menuDidClose : (NSMenu *) someMenu
{
    if (someMenu == self.statusMenu)
    {
            // re-configure statusitem
            self.statusItem.menu = nil;
            [self.statusItem.button sendActionOn: (NSLeftMouseUpMask|NSRightMouseUpMask)];
            [self.statusItem.button setAction: @selector(statusItemClicked:)];
    }
}

Upvotes: 0

eemmrrkk
eemmrrkk

Reputation: 1700

"If the status item has a menu set, the action is not sent to the target when the status item is clicked; instead, the click causes the menu to appear."- apple dev NSStatusItem.action

Upvotes: 3

Related Questions