I have a UIViewController
with a UICollectionView
and a UITableView
. Both views use UICollectionViewDiffableDataSource
and UITableViewDiffableDataSource
respectively.
In the table, I am trying to set up swipe functionality for the delete action. It was a very simple task with a regular data source, but I can't get it to work with the diffable one.
I tried creating a custom class for UITableViewDiffableDataSource
, but I wasn't even able to compile the code with my attempts to access the property from the controller. (I needed to access the property storing the model to delete not only the row, but also the data.) Using UITableViewDelegate
with a tableView(leadingSwipeActionsConfigurationForRowAt:)
did compile, and I could swipe, but the app crashed with an error: UITableView must be updated via the UITableViewDiffableDataSource APIs when acting as the UITableView's dataSource.
How do I do it? Is there a best practice for a job like this?
Edit 1:
As requested in the comments, I'm providing some of my code, for the most recent attempt at implementation.
In the UIViewController
(it's a long implementation, so I left out most of it):
class ViewController: UIViewController, ItemsTableViewDiffableDataSourceDelegate {
@IBOutlet var tableView: UITableView!
var items = [Item]()
var tableViewDataSource: ItemsTableViewDiffableDataSource!
var itemsSnapshot: NSDiffableDataSourceSnapshot<String, Item> {
var snapshot = NSDiffableDataSourceSnapshot<String, Item>()
snapshot.appendSections(["Items"])
snapshot.appendItems(items)
return snapshot
}
func configureTableViewDataSource() {
// A working implementation
}
func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
let deleteAction = UIContextualAction(style: .destructive, title: "Delete") { action, view, handler in
self.items.remove(at: indexPath.row)
tableView.deleteRows(at: [indexPath], with: .fade)
}
deleteAction.backgroundColor = .red
let configuration = UISwipeActionsConfiguration(actions: [deleteAction])
configuration.performsFirstActionWithFullSwipe = false
return configuration
}
}
In the UITableViewDiffableDataSource
(complete implementation):
@MainActor
class ItemsTableViewDiffableDataSource: UITableViewDiffableDataSource<String, Item> {
}
protocol ItemsTableViewDiffableDataSourceDelegate: AnyObject {
func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration?
}
Originally, I had the tableView(leadingSwipeActionsConfigurationForRowAt:)
method defined within the data source class, but I couldn't access the items
property, so I tried it with a protocol. Either way, the implementation doesn't work — I'm unable to swipe, let alone delete items and table rows.
Edit 2:
I guess the real question is — how do I register the tableView(leadingSwipeActionsConfigurationForRowAt:)
method with my tableView
. Still, my guess is that my implementation is faulty in general.