I am trying to make my tableView cells
movable, but it needs 2 or 3 functions from UITableViewDataSource
protocol, If I tried to implement the delegate in my viewController
It will ask for numberOfRowsInSection
and cellForRowAtIndexPath
functions which are already covered by the new UITableViewDiffableDataSource
.
How can I achieve this behavior while using the new UITableViewDiffableDataSource
?
To flesh out Tung Fam's answer, here is a complete implementation:
class MovableTableViewDataSource: UITableViewDiffableDataSource<Int, Int> {
override func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
super.tableView(tableView, moveRowAt: sourceIndexPath, to: destinationIndexPath)
var snapshot = self.snapshot()
if let sourceId = itemIdentifier(for: sourceIndexPath) {
if let destinationId = itemIdentifier(for: destinationIndexPath) {
guard sourceId != destinationId else {
return // destination is same as source, no move.
}
// valid source and destination
if sourceIndexPath.row > destinationIndexPath.row {
snapshot.moveItem(sourceId, beforeItem: destinationId)
} else {
snapshot.moveItem(sourceId, afterItem: destinationId)
}
} else {
// no valid destination, eg. moving to the last row of a section
snapshot.deleteItems([sourceId])
snapshot.appendItems([sourceId], toSection: snapshot.sectionIdentifiers[destinationIndexPath.section])
}
}
apply(snapshot, animatingDifferences: false, completion: nil)
}
}
It will crash if animatingDifferences
is set true (animating is not really desirable here anyway).
I'm not sure whether calling super.tableView(move…)
is necessary, but it doesn't seem to do any harm.