To display list of items, I'm using UITableView which conforms to UITableViewDiffableDataSource. I want to reorder table rows. For that I've used tableView(_:canMoveRowAt:) and tableView(_:moveRowAt:to:). I couldn't see reorder button on the cells and both delegate functions are not triggered.
But when I change the datasource to normal UITableViewDataSource , reordering is working.
import UIKit
import CoreData
typealias NewsItemDataSource = UITableViewDiffableDataSource<String, NSManagedObjectID>
typealias NewsItemSnapshot = NSDiffableDataSourceSnapshot<String, NSManagedObjectID>
class NewsItemViewController: UIViewController {
private var tableView: UITableView!
private var diffableDatasource: NewsItemDataSource!
override func viewDidLoad() {
super.viewDidLoad()
configureTableView()
performFetch()
}
private func performFetch() {
do {
try fetchedResultsController.performFetch()
} catch {
}
}
private func configureTableView() {
tableView = UITableView()
tableView.register(with: NewsItemTableViewCell.self) // refactored with extension
diffableDatasource = playsDiffableDataSource(tableView)
tableView.dataSource = diffableDatasource
tableView.isEditing = true
tableView.allowsSelection = false
tableView.delegate = self
}
func playsDiffableDataSource(_ tableView: UITableView) -> UITableViewDiffableDataSource<String, NSManagedObjectID> {
let diffableDatasource = UITableViewDiffableDataSource<String, NSManagedObjectID>(tableView: tableView) { (tableView, indexPath, objectID) -> UITableViewCell? in
guard let newsItem = try? CoreDataManager.shared.moc.existingObject(with: objectID) as? CDNewsItem else {
return UITableViewCell()
}
let cell: NewsItemTableViewCell = tableView.dequeueReusableCell(for: indexPath)
cell.configure(with: newsItem)
return cell
}
return diffableDatasource
}
private lazy var fetchedResultsController: NSFetchedResultsController<CDNewsItem> = {
// Create Fetch Request
let fetchRequest = CDNewsItem.fetchRequest()
// Configure Fetch Request
fetchRequest.sortDescriptors = [NSSortDescriptor(key: "modificationDate", ascending: false)]
fetchRequest.fetchBatchSize = 30
// Create Fetched Results Controller
let moc = CoreDataManager.shared.moc
let fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest,
managedObjectContext: moc,
sectionNameKeyPath: nil,
cacheName: nil)
// Configure Fetched Results Controller
fetchedResultsController.delegate = self
return fetchedResultsController
}()
func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
return true
}
func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
fetchedResultsController.fetchedObjects?.swapAt(sourceIndexPath.row, destinationIndexPath.row)
}
func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCell.EditingStyle {
return .none
}
func tableView(_ tableView: UITableView, shouldIndentWhileEditingRowAt indexPath: IndexPath) -> Bool {
return false
}
}
extension PlaysListViewController: NSFetchedResultsControllerDelegate {
func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChangeContentWith snapshot: NSDiffableDataSourceSnapshotReference) {
guard let diffableDatasource else { return }
diffableDatasource.apply(snapshot as NewsItemSnapshot, animatingDifferences: true)
}
}