Search code examples
swiftmacoscocoaselectorappkit

NSSegmentedControl action not firing


I am not using any Storyboards/NIBs, I'm creating all my UI programmatically.

Here's the main window controller:

class MainWindowController: NSWindowController, NSToolbarDelegate {

    var toolbar: NSToolbar!
    var segmentedControl: NSSegmentedControl!

    override func loadWindow() {
        self.window = NSWindow(contentRect: .init(origin: .zero, size: .init(width: 640, height: 480)),
                               styleMask: NSWindow.StyleMask(rawValue: (NSWindow.StyleMask.closable.rawValue | NSWindow.StyleMask.titled.rawValue | NSWindow.StyleMask.miniaturizable.rawValue | NSWindow.StyleMask.resizable.rawValue)),
                               backing: .buffered, defer: true)
    }

    override init(window: NSWindow?) {
        super.init(window: window)
        loadWindow()

        self.window?.center()

        self.segmentedControl = NSSegmentedControl(labels: ["1", "2", "3"], trackingMode: NSSegmentedControl.SwitchTracking.selectOne, target: self, action: #selector(switchTabs))
        self.segmentedControl.setSelected(true, forSegment: 0)

        self.toolbar = NSToolbar(identifier: .init("MainToolbar"))
        self.toolbar.delegate = self
        self.toolbar.displayMode = .iconOnly
        self.window?.toolbar = self.toolbar

        self.window?.contentViewController = MainSplitViewController()
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    // MARK: - Selectors

    @objc func switchTabs(sender: Any) {
        let segmentedControl = sender as! NSSegmentedControl
        let tabVC = (self.window!.contentViewController as! MainSplitViewController!).tabViewController
        tabVC.tabView.selectTabViewItem(at: segmentedControl.selectedSegment)
    }

    // MARK: - NSToolbarDelegate

    func toolbarDefaultItemIdentifiers(_ toolbar: NSToolbar) -> [NSToolbarItem.Identifier] {
        return [
            NSToolbarItem.Identifier.init("Add"),
            NSToolbarItem.Identifier.flexibleSpace,
            NSToolbarItem.Identifier.init("NSSegmentedControl"),
            NSToolbarItem.Identifier.flexibleSpace,
            NSToolbarItem.Identifier.init("Search")
        ]
    }

    func toolbarAllowedItemIdentifiers(_ toolbar: NSToolbar) -> [NSToolbarItem.Identifier] {
        return [
            NSToolbarItem.Identifier.flexibleSpace,
            NSToolbarItem.Identifier.init("NSSegmentedControl"),
            NSToolbarItem.Identifier.init("Search"),
            NSToolbarItem.Identifier.init("Add")
        ]
    }

    func toolbar(_ toolbar: NSToolbar, itemForItemIdentifier itemIdentifier: NSToolbarItem.Identifier, willBeInsertedIntoToolbar flag: Bool) -> NSToolbarItem? {
        switch itemIdentifier {
        case NSToolbarItem.Identifier.flexibleSpace:
            return NSToolbarItem(itemIdentifier: itemIdentifier)
        case NSToolbarItem.Identifier.init("NSSegmentedControl"):
            let toolbarItem = NSToolbarItem(itemIdentifier: itemIdentifier)
            toolbarItem.view = self.segmentedControl
            return toolbarItem
        case NSToolbarItem.Identifier.init("Search"):
            let toolbarItem = NSToolbarItem(itemIdentifier: itemIdentifier)
            let searchField = NSSearchField(frame: NSRect(origin: .zero, size: CGSize(width: 64, height: 64 )))
            toolbarItem.view = searchField
            return toolbarItem
        case NSToolbarItem.Identifier.init("Add"):
            let toolbarItem = NSToolbarItem(itemIdentifier: itemIdentifier)
            let addButton = NSButton(title: "Add", target: self, action: nil)
            toolbarItem.view = addButton
            return toolbarItem
        default:
            return nil
        }
    }

}

I have three NSViewControllers embedded in an NSTabViewController in my window. I want to be able to connect them to the selection of the NSSegmentedControl in my NSToolbar.

However, the action is never being fired. The switchTabs method is never being called. If I call the function directly, then it works! But nothing happens when I select a NSSegmentedCell.

What's going wrong here?

Am I doing the instantiation of the window correctly? Is my usage of loadWindow correct?


Solution

  • I was not able to get this working in it's current set up, so I set the target and action to my NSTabViewController and a selector in that class.