Reputation: 146
I try to use UITableViewDiffableDataSource
class SecondViewController: UIViewController {
enum Section {
case main
}
struct Model: Hashable {
let title: String
}
var tableView: UITableView!
var dataSource: UITableViewDiffableDataSource<Section, Model>!
override func viewDidLoad() {
super.viewDidLoad()
tableView = UITableView(frame: view.bounds)
view.addSubview(tableView)
tableView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
view.layoutIfNeeded()
dataSource = UITableViewDiffableDataSource<Section, Model>(tableView: tableView, cellProvider: { (tableView, indexPath, item) -> UITableViewCell? in
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.text = item.title
return cell
})
var snapshot = NSDiffableDataSourceSnapshot<Section, Model>()
snapshot.appendSections([.main])
snapshot.appendItems([Model(title: "1")], toSection: .main)
dataSource.apply(snapshot)
}
}
if I use view.layoutIfNeeded()
before create dataSource
, it will crash:
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of sections. The number of sections contained in the table view after the update (1) must be equal to the number of sections contained in the table view before the update (1), plus or minus the number of sections inserted or deleted (1 inserted, 0 deleted).'
Upvotes: 7
Views: 2380
Reputation: 1492
Same problem, I found that even without animations, some users in production will still crash。
When I setupUI in viewDidLoad
, DispatchQueue.main.async
help me fix this problem
DispatchQueue.main.async { [weak self] in
guard let self = self else { return }
var snapshot = NSDiffableDataSourceSnapshot<Section, Row>()
snapshot.appendSections([...])
snapshot.appendItems([...], toSection: .main)
dataSource.apply(snapshot, animatingDifferences: true, completion: nil)
}
More specifically, just setting animatingDifferences
to false
will still crash. This crash only happened on iOS 15.0.0 and iOS15.0.1
Upvotes: 0
Reputation: 2609
I ran into the same problem. In general, on iOS 14, causing a layout before the table view's data source is set can cause crashes.
You can fix these crashes by setting the data source as soon as the table view has been created. If you want to animate your initial snapshot, then first set an empty snapshot followed by a populated one with animatingDifferences: true
.
Upvotes: 0
Reputation: 199
I encountered the same problem, when populating a UITableView
with results from a PassthroughSubject
, as soon as the UIViewController
was displayed.
Animating updates was very important to me, so my workaround was to first "prime" the DiffableDataSource
by creating a snapshot immediately after initialisation, appending the sections I wanted, appending the items with an empty array, and applying the snapshot with animatingDifferences: false
.
Afterwards I was able to apply animated snapshots with data with no issue.
Upvotes: 6