Summary
NSTableViewDiffableDataSource does not trigger the tableView(_:rowViewForRow:) delegate method when used, unlike traditional data source implementations. This behavior is due to the diffable data source’s internal handling of row views.
Root Cause
- Diffable data source manages row views internally, bypassing the need to call
tableView(_:rowViewForRow:). - The method is not invoked because the diffable data source assumes default row view behavior.
Why This Happens in Real Systems
- Design choice: Diffable data sources prioritize simplicity and performance by managing row views internally.
- Assumption of default behavior: It assumes no custom row view configuration is needed unless explicitly overridden.
Real-World Impact
- Custom row views break: Developers relying on
tableView(_:rowViewForRow:)for customization cannot use diffable data sources without a workaround. - Code migration issues: Projects transitioning to diffable data sources may encounter unexpected behavior in table view rendering.
Example or Code
class ViewController: NSViewController, NSTableViewDelegate {
@IBOutlet var tableView: NSTableView!
var datasource: NSTableViewDiffableDataSource!
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
datasource = NSTableViewDiffableDataSource(tableView: tableView) { tableView, _, row, _ in
// Cell configuration
}
var snapshot = NSDiffableDataSourceSnapshot()
snapshot.appendSections(["dummy"])
snapshot.appendItems(["manny", "moe", "jack"])
datasource.apply(snapshot)
}
func tableView(_ tableView: NSTableView, rowViewForRow row: Int) -> NSTableRowView? {
print("here") // NOT CALLED
return NSTableRowView()
}
}
How Senior Engineers Fix It
- Subclass NSTableRowView: Create a custom row view subclass and register it with the table view.
- Use
tableView(_:viewFor:): Leverage the diffable data source’s cell configuration closure to customize row views indirectly. - Report and workaround: File a bug report to Apple and use traditional data sources if custom row views are essential.
Why Juniors Miss It
- Lack of understanding: Juniors may not realize diffable data sources handle row views differently.
- Overlooking documentation: Apple’s documentation does not explicitly state that
tableView(_:rowViewForRow:)is unused with diffable data sources. - Assumption of parity: Assuming diffable data sources behave identically to traditional data sources leads to unexpected behavior.