Search code examples
cocoatableview

Components of NSDatePicker inside NSTableView cannot be selected


In my table view, each row contains a popup button and a date picker. When clicking on the popup button, it behaves as expected: the menu appears and I can change the selected item. But when clicking on the date components of the date picker, the table view row is selected, as if I'm clicking on a non-interactive control (e.g. when clicking on a non-editable text field, the table view selection changes as well). Only when clicking on the stepper (the up/down arrows on the right) does the first date component get selected, which then allows me to click on the other ones as well.

enter image description here

Can I change this behaviour so that clicking on the date picker behaves as if I'm directly interacting with it, instead of the table view?


Solution

  • The date picker seems to act differently than a text field in a table view. While I can activate text fields with the first click, clicking on a date picker first selects the table row, and the second click then selects the date picker component.

    When disabling the table view selection with NSTableViewDelegate.tableView(_:shouldSelect:) and returning false, while text fields can still be activated, date pickers don't respond anymore (unless clicking first on the stepper on the right).

    Still, the solution from other answers (as mentioned in the comment by @Willeke), works here too.

    class MyTableView: NSTableView {
        
        override func hitTest(_ point: NSPoint) -> NSView? {
            let myPoint = superview!.convert(point, to: self)
            let column = column(at: myPoint)
            let row = row(at: myPoint)
            if row >= 0, column >= 0, let cell = view(atColumn: column, row: row, makeIfNecessary: false), let datePicker = cell.hitTest(convert(myPoint, to: cell.superview)) as? NSDatePicker {
                return datePicker
            } else {
                return super.hitTest(point)
            }
        }
        
    }