Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

321
Views
View-based NSTableView not applying partial reloads with DifferenceKit

I'm using an NSTableView and DifferenceKit. 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 code (truncated):

init() {
    ...
    tableView.dataSource = self
    tableView.delegate = self
    columns.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? {
    ...
    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
}
over 4 years ago · Santiago Trujillo
1 answers
Answer question

0

This turns out to be either a misunderstanding of, or possibly a bug in, the way DifferenceKit interacts with a view-based, rather than cell-based, NSTableView.

I was crucially not checking the values with which reloadData(forRowIndexes:columnIndexes) was called, and the columnIndexes passed by DifferenceKit's algorithm were always [0], which was not valid for any visible cells as my first column is hidden, so the methods weren't called.

The useful lesson here is that when a tableview's delegate lacks tableView(_:viewFor:row:), a reload to any column reloads the entire row, but once views are specified, the column values become relevant.

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!