When Actions of NSSegmentedControl in Toolbars Do Not Fire In Their Overflow Menu Item State, Do This

In this fourth and probably still not final part of my series on NSToolbarItems with segmented controls, I just want to share a problem and a quick fix that Nathan Manceaux-Panot brought up today.

The series spans 8 years and is this:

  1. Original Approach
  2. Enabling/Disabling Segments
  3. Fixing the action dispatching bug
  4. Fixing action dispatching within overflow menus (this post)

Nathan recently went through the series to implement segmented controls in toolbars but discovered that the overflow menu items would not enable (a validation problem) and when they enable, they don’t fire the action. When he brought this up today, I investigated.

I’m using this approach in TableFlip and bypassed the validation problem with a custom validation logic. So I was safe there.

But some of the menu items were indeed clickable without producing any effect. Uh oh.

The fix is quite simple: make sure you assign the NSToolbarItem’s action. That’s being used when the overflow menu item representations are assembled.

extension ToolbarSegmentedControlSegment {
    func toolbarItem() -> NSToolbarItem {
        let item = NSToolbarItem(itemIdentifier: toolbarItemIdentifier)
        item.label = label
        item.action = action  // Make sure to set this!
        item.menuTitle = menuTitle
        item.menuImage = menuImage
        item.updateMenuFormRepresentation()
        return item
    }
}

Looking at this code out of context, you might wonder how on earth the toolbar item was supposed to work at all without an action.

It worked because outside its overflow menu item representation, the toolbar item didn’t have to handle clicks anyway. The NSSegmentedControl handled interaction with its segments.