Search code examples
swiftmacoscocoanstableview

Some TableView views are not reloading, as my TableView Delegate is not receiving tableView:viewFor:row: for every row


I have a TableView, and a TableViewController

The TableView's delegate and datasource are set to the TableViewController

So when the table goes to draw, it asks the delegate for the views, and this code runs:

func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {

    let result = tableView.make(withIdentifier: "flagView", owner: self) as? TableCellView

    case "technicalFlag", "supplyFlag":
        let button = result?.control as? NSButton {
            button.state = value.boolValue ? NSOnState : NSOffState
        }
     }

Which updates the buttons properly:
enter image description here

Notice how there are 5 flags for Technical Risk

However, when I go to sort by Supply Risk, it calls tableView.reloadData()

But, not every view gets reloaded?

As a result, some of the flags stay black, even when they shouldn't be (notice 8+ black flags in Technical Risk, now)

enter image description here

It's seemingly random which flags are black (when I look at the data via another view via context menu, I can tell which flags should truly be black)

So ostensibly, it looks like a redrawing issue. I've tried everything, but can't get those views to redraw. Am I missing something?

I've confirmed that tableView:viewFor:row: is just not getting called as many times as I think it should

I guess, to sum things up, I thought that calling reloadData() would update every view at every row x column? How does the runtime decide which views get the update call?


Solution

  • Ah solved it, I had modified the original code because I didn't think it was relevant to show:

        case "technicalRiskFlag", "supplyRisk":
            if let value = node.value(forKeyPath: identifier) as? NSNumber,
            let button = result?.control as? NSButton {
                button.state = value.boolValue ? NSOnState : NSOffState
            }
    

    But turns out that value could be nil, which ended up not redrawing the flag. Not sure why the delegate method didn't get called still, but I changed the code to this:

            if let button = result?.control as? NSButton {
                if let value = node.value(forKeyPath: identifier) as? NSNumber {
                    button.state = value.boolValue ? NSOnState : NSOffState
                } else {
                    button.state = NSOffState
                }
            }
    

    and it works perfect now