Implementing NSSegmentedControl in NSToolbar to control NSTabViewController

Home / Uncategorized / Implementing NSSegmentedControl in NSToolbar to control NSTabViewController

Question:
In my macOS application, I’m trying to replicate the Photos.app implementation of NSSegmentedControl in NSToolbar to control an NSTabViewController. For reference, here’s what that looks like:

So, my approach was as follows:Hide the default NSTabView header using the Interface Builder
Programmatically add an NSToolbar
Insert NSSegmentedControl as an NSToolbarItem.
Use a #selector to listen for changes to NSSegmentedControl.

Here’s the current implementation:class WindowController: NSWindowController, NSToolbarDelegate {

// MARK: – Identifiers

let mainToolbarIdentifier = NSToolbar.Identifier("MAIN_TOOLBAR")
let segmentedControlIdentifier = NSToolbarItem.Identifier("MAIN_TABBAR")

// MARK: – Properties

var tabBar: NSSegmentedControl? = NSSegmentedControl(labels: ["One", "Two"], trackingMode: NSSegmentedControl.SwitchTracking.selectOne, target: self, action: #selector(didSwitchTabs))
var toolbar: NSToolbar?
var tabBarController: NSTabViewController?

// MARK: – Life Cycle

override func windowDidLoad() {
super.windowDidLoad()

self.toolbar = NSToolbar(identifier: mainToolbarIdentifier)
self.toolbar?.allowsUserCustomization = false
self.toolbar?.delegate = self

self.tabBar?.setSelected(true, forSegment: 0)

self.tabBarController = self.window?.contentViewController as? NSTabViewController
self.tabBarController?.selectedTabViewItemIndex = 0

self.window?.toolbar = self.toolbar
}

// MARK: – NSToolbarDelegate

public func toolbar(_ toolbar: NSToolbar, itemForItemIdentifier itemIdentifier: NSToolbarItem.Identifier, willBeInsertedIntoToolbar flag: Bool) -> NSToolbarItem? {

var toolbarItem: NSToolbarItem

switch itemIdentifier {
case segmentedControlIdentifier:toolbarItem = NSToolbarItem(itemIdentifier: segmentedControlIdentifier)
toolbarItem.view = self.tabBar
case NSToolbarItem.Identifier.flexibleSpace:toolbarItem = NSToolbarItem(itemIdentifier: itemIdentifier)
default:fatalError()
}

return toolbarItem
}

public func toolbarAllowedItemIdentifiers(_ toolbar: NSToolbar) -> [NSToolbarItem.Identifier] {
return [segmentedControlIdentifier, NSToolbarItem.Identifier.flexibleSpace]
}

public func toolbarDefaultItemIdentifiers(_ toolbar: NSToolbar) -> [NSToolbarItem.Identifier] {
return [NSToolbarItem.Identifier.flexibleSpace, segmentedControlIdentifier, NSToolbarItem.Identifier.flexibleSpace]
}

// MARK: – Selectors

@objc func didSwitchTabs(sender: Any) {

let segmentedControl = sender as! NSSegmentedControl

if (segmentedControl.selectedSegment == 0) {
self.tabBarController?.selectedTabViewItemIndex = 0
} else if (segmentedControl.selectedSegment == 1) {
self.tabBarController?.selectedTabViewItemIndex = 1
}
}

}

And, here it is in action:

Now, I am new to macOS development and this feels like it’s a very complicated and convoluted way of solving this problem. Is there an easier way I could achieve the same thing ? Perhaps somehow in Interface Builder ? What could be done to improve here ? What have I done wrong ?

Thanks for your time.


Answer:

Read more

Leave a Reply

Your email address will not be published. Required fields are marked *