Search code examples
swiftmacosdelegatesmenubar

Menubar with Storyboard - validateMenuItem not get called


I'm trying to setup a menubar Application using storyboard but my validateMenuItem method not get called.

I will try to explain what i did. First i dragged a Menu Item in my Application Scene. Then one Object for my MenuController. Created a MenuController (MenuController.swift) and filled it with code. Back in my storyboard I set my Menu delegate to MenuController and MenuController Outlet to Menu. (I'm not totally sure whether i have set the delegates correctly.)

When i start the app, the menu icon appears and the first item title is set to test. But when i'm clicking the icon the validateMenuItem method not get called.

MenuController.swift

import Cocoa
class MenuController: NSObject {

    var statusItem = NSStatusBar.systemStatusBar().statusItemWithLength(-1)

    @IBOutlet weak var statusMenu: NSMenu!
    @IBOutlet weak var item1: NSMenuItem!

    override func awakeFromNib() {
        print("awakeFromNib")

        self.item1.title = "Test"

        let icon = NSImage(named: "menubarIcon")
        statusItem.image = icon
        statusItem.menu = statusMenu
    }

    override func validateMenuItem(menuItem: NSMenuItem) -> Bool {
        print("validateMenuItem")
        return true
    }
}

Storyboard Menu Delegates Storyboard Menu Delegates
(source: picr.de)

Storyboard MenuController Delegates Storyboard MenuController Delegates
(source: picr.de)

Has anybody an idea?

Greets from Austria!


Solution

  • The menu/UI validation mechanism does not query the menu's delegate but uses the item's target to determine the enabled state instead.
    If the target is not explicitly set, it walks the responder chain.

    To get basic validation, you have to make sure that the following things are setup:

    • "Auto Enables Items" is checked in Interface Builder (on by default)
    • You control-dragged the menu's action to the first responder
    • The menu's action is implemented in a class that is part of the responder chain (e.g. a view controller that manages a set of actions for your UI)

    A basic implementation of validateUserInterfaceItem: could look like the following for an item with an action selector called test:

    func validateUserInterfaceItem(anItem: NSValidatedUserInterfaceItem) -> Bool
    {
        if anItem.action() == Selector("test:") {
            print("validating item \(anItem)")
            return true
        }
        return true
    }