In the following code example
import UIKit
struct Language: Hashable {
let name: String
}
enum Section {
case main
}
class ViewController: UIViewController, UITableViewDelegate {
var tableView: UITableView!
private typealias DataSource = UITableViewDiffableDataSource<Section, Language?>
private var dataSource: DataSource!
override func viewDidLoad() {
super.viewDidLoad()
// Set up the table view
tableView = UITableView(frame: view.bounds)
view.addSubview(tableView)
// Register a simple cell
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
// Set up the data source
dataSource = DataSource(tableView: tableView) { tableView, indexPath, language in
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
// Check if the language is nil and configure the cell accordingly
if let language = language {
cell.textLabel?.text = language.name
} else {
cell.textLabel?.text = "No Language"
}
return cell
}
// Set up the snapshot with some sample data including nil
var snapshot = NSDiffableDataSourceSnapshot<Section, Language?>()
snapshot.appendSections([.main])
snapshot.appendItems([Language(name: "English"), nil, Language(name: "Spanish"), Language(name: "French")])
// Apply the snapshot to the data source
dataSource.apply(snapshot, animatingDifferences: true)
tableView.delegate = self
}
}
I am getting runtime error
Could not cast value of type 'NSNull' (0x1ec78e900) to 'xxx.Language' (0x1008e0468).
Is UITableViewDiffableDataSource
not supporting nil
? I can't find https://developer.apple.com/documentation/uikit/uitableviewdiffabledatasource talks about this limitation.
Thanks.
The documentation for NSDiffableDataSourceSnapshot
states:
Important
Each of your sections and items must have unique identifiers that conform to the Hashable protocol.
nil
cannot satisfy this requirement.
Because UITableView
is Objective-C, the nil
has been translated to the special singleton NSNull
which also cannot satisfy this requirement. NSNull
also cannot be converted to an instance of Language
, which is the error you are getting.
While the documentation doesn't explicitly state that you can't add nil
, the requirement for items to have unique identifiers strongly implies this.
In fact, using an optional as your item type is the error that should be flagged. This doesn't make sense. Your snapshot is the items that exist. If an item doesn't exist you simply don't add it to the snapshot
While the reason for the error you get many not be immediately obvious and it would be better for your error of declaring an optional type as your item type to be flagged at compile time, the behaviour seems reasonable in the circumstances.