gbdavid gbdavid - 1 month ago 22
Swift Question

NSTableView detect NSTableColumn for selected cell at start of cell edition

I'm trying to programatically get get a a column.identifier for the cell that is being edited. I'm trying to get by registering my NSViewController for NSControlTextDidBeginEditingNotification and when I get the notification I track the data by mouse location:

var selectedRow = -1
var selectedColumn: NSTableColumn?

func editingStarted(notification: NSNotification) {
selectedRow = participantTable.rowAtPoint(participantTable.convertPoint(NSEvent.mouseLocation(), fromView: nil))

let columnIndex = participantTable.columnAtPoint(participantTable.convertPoint(NSEvent.mouseLocation(), fromView: nil))
selectedColumn = participantTable.tableColumns[columnIndex]

}


The problem I have is that the mouse location is giving me the wrong data, is there a way to get the mouse location based on the location of the table, or could there be a better way to get this information?

PS. My NSViewController is NSTableViewDelegate and NSTableViewDataSource, my NSTableView is View Based and connects to an ArrayController which updates correctly, and I could go to my Model object and detect changes in the willSet or didSet properties, but I need to detect when a change is being made by the user and this is why I need to detect the change before it happens on the NSTableView.

Answer

This question is 1 year old but I got the same issue today and fixed it. People helped me a lot here so I will contribute myself if someone found this thread.
Here is the solution :

1/ Add the NSTextFieldDelegate to your ViewController :

class ViewController: NSViewController, NSTableViewDelegate, NSTableViewDataSource, NSTextFieldDelegate {

2/ When a user wants to edit a cell, he had first to select the row. So we will detect that with this delegate function :

    func tableViewSelectionDidChange(_ notification: Notification) {
        let selectedRow = self.tableView.selectedRow

        // If the user selected a row. (When no row is selected, the index is -1)
        if (selectedRow > -1) {
        let myCell = self.tableView.view(atColumn: self.tableView.column(withIdentifier: "myColumnIdentifier"), row: selectedRow, makeIfNecessary: true) as! NSTableCellView

        // Get the textField to detect and add it the delegate
        let textField = myCell.textField
        textField?.delegate = self
    }
}

3/ When the user will edit the cell, we can get the event (and the data) with 3 different functions. Pick the ones you need :

override func controlTextDidBeginEditing(_ obj: Notification) {
    // Get the data when the user begin to write
}

override func controlTextDidEndEditing(_ obj: Notification) {
    // Get the data when the user stopped to write
}

override func controlTextDidChange(_ obj: Notification) {
    // Get the data every time the user writes a character
}