I'm using an NSTableView
(and DifferenceKit, but that's likely irrelevant). This is all programmatic, no Interface Builder at all.
I'd previously implemented only tableView(_:objectValueFor:row)
in order to get values into my table. At that point I could apply full and partial reloads and everything worked fine.
Now I've added an implementation of tableView(_:viewFor:row:)
in order to format some columns differently, and it's affected reloading. A full reloadData()
still works, but a call to reloadData(forRowIndexes:columnIndexes)
doesn't call either my datasource or delegate methods; the reload seems to simply disappear.
I also tried removing the datasource method and running only with tableView(_:viewFor:row:)
but no dice. A partial reload still doesn't call the delegate method.
Has anyone come across this? Is there a nuance of NSTableView I'm missing?
My (truncated) code:
init() {
...
tableView.dataSource = self
tableView.delegate = self
myColumnDefinitions.forEach {
tableView.addTableColumn($0)
}
}
func tableView(
_ tableView: NSTableView,
objectValueFor tableColumn: NSTableColumn?,
row: Int
) -> Any? {
...
return someStringProvider(column, row)
}
func tableView(
_ tableView: NSTableView,
viewFor tableColumn: NSTableColumn?,
row: Int
) -> NSView? {
...
let identifier = someDerivedValue(column)
if let existingView = tableView.makeView(withIdentifier: identifier, owner: self) as? NSTableCellView {
existingView.textField?.stringValue = someStringProvider(column, row)
return existingView
}
let textField = NSTextField()
...
textField.stringValue = someStringProvider(column, row)
let view = NSTableCellView()
view.identifier = identifier
view.addSubview(textField)
view.textField = textField
view.addConstraints([
... (pin textField to view)
])
textField.bind(
.value,
to: view,
withKeyPath: "objectValue",
options: nil
)
return view
}