Company logo
  • Jobs
  • Bootcamp
  • About Us
  • For professionals
    • Home
    • Jobs
    • Courses
    • Questions
    • Teachers
    • Bootcamp
  • For business
    • Home
    • Our process
    • Plans
    • Assessments
    • Payroll
    • Blog
    • Calculator

0

128
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
}
10 months 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.

10 months ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post job Plans Our process Sales
Legal
Terms and conditions Privacy policy
© 2023 PeakU Inc. All Rights Reserved.