5
votes

for those not into reading 20 comments to look for the answer. here is what worked for me:

  1. the tableView is View Based, not Cell Based (attributes inspector)
  2. tableView.reloadData() wasn’t fast enough. using insertRow(at[0]:withAnimation:.leftSlide) instead worked fine
  3. make sure that the NSTextField as well as the NSTextFieldCell are editable (attributes inspector)

the final code:

tableViewAlarms.insertRows(at: [0], withAnimation: .effectFade)

let keyView = tableViewAlarms.view(atColumn: 0, row: 0, makeIfNecessary: false) as! NSTableCellView

self.view.window!.makeFirstResponder(keyView.textField)

the question:

got one question. I have been stuck for some time making my NSTableView work the way I want it to. I'm a beginner and working with classes, inheritance, and views is giving me a lot of trouble.

screenshot, the NSTextField is activated

you add a row to the NSTableView by pushing the '+' button.

the NSTextField in the first tableColumn is editable and begins editing when double-clicked

now I want the NSTextField in the first column to be activated automatically (show cursor, responding to text input via keyboard) when a row is added.

so far i have tried:

class NSTextFieldSubClass: NSTextField {

    override func becomeFirstResponder() -> Bool {
        return true
    }

}

I also played around with the bindings of the cell (or the NSTextField itself to be precise), but since I don't really know my way around those it went nowhere

what I think is the way to go:

make the NSTextField the firstResponder when the cell is created, but I don't know how. Any help is greatly appreciated!!

also: how exactly is the state of an NSTextField called when the cursor is blinking?

edit:

as for the subclass, this is all I tried:

class NSTextFieldSubClass: NSTextField {

    override func becomeFirstResponder() -> Bool {
        return true
    }

}

edit screenshot:

these are the connections

edit2:

edit2: attributes inspector tableView

edit3:

edit3: bindings NSTextField

edit4:

edit4: error

2
anyone? would help a lot!felixmp

2 Answers

3
votes

At the end of the action method of the '+' button, after adding the row do:

DispatchQueue.main.async(execute: {
    // get the cell view
    let view = self.tableView.view(atColumn: 0, row: row, makeIfNecessary: false)
    if let cellView = view as? NSTableCellView {
        // get the text field
        if let textField = cellView.textField {
            // make the text field first responder
            if textField.acceptsFirstResponder {
                self.tableView.selectRowIndexes(IndexSet(integer:row), byExtendingSelection: false)
                self.tableView.window?.makeFirstResponder(textField)
            }
        }
    }
})
2
votes

Don't subclass NSTextField. You can make the text field in a view based table view first responder right out of the box.

It's pretty easy.

Assuming you know row and column (in your example row 0 and column 0) get the table cell view with view(atColumn: 0, row and make the text field first responder.

let keyView = tableView.view(atColumn: 0, row: 0, makeIfNecessary: false) as! NSTableCellView
view.window!.makeFirstResponder(keyView.textField)

And what is the second outlet for? Just use the standard default textField.