mi sono imbattuto in un problema simile quando sono ordinati su "DateModified", ma mi è stato anche la visualizzazione che la proprietà sull'etichetta della cellula. Sono stati richiesti sia "move" che "update". "move" è stato chiamato solo così la cella corretta è stata portata in cima alla lista, ma il testo dell'etichetta non è stato aggiornato.
La mia soluzione per un UITableViewCell semplice.
Innanzitutto, si effettua la chiamata .move normalmente. Subito dopo aver effettuato una chiamata a un metodo di configurazione personalizzato, che è responsabile dell'animazione dell'aggiornamento nella cella.
func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) {
switch type {
case .insert:
tableView.insertRows(at: [newIndexPath!], with: .fade)
case .delete:
tableView.deleteRows(at: [indexPath!], with: .fade)
case .update:
tableView.reloadRows(at: [indexPath!], with: .fade)
case .move:
tableView.moveRow(at: indexPath!, to: newIndexPath!)
// Can't "reload" and "move" to same cell simultaneously.
// This is an issue because I'm sorting on date modified and also displaying it within a
// label in the UITableViewCell.
// To have it look perfect you have to manually crossfade the label text, while the UITableView
// does the "move" animation.
let cell = tableView.cellForRow(at: indexPath!)!
let note = fetchedResultsController.object(at: newIndexPath!)
configure(cell: cell, note: note, animated: true)
}
}
Il metodo di configurazione è simile a questo (nota animato è opzionale):
internal func configure(cell: UITableViewCell, note: Note, animated: Bool = false) {
let dateFormatter = DateFormatter()
dateFormatter.dateStyle = .medium
dateFormatter.timeStyle = .medium
let dateString = dateFormatter.string(from: note.dateModified as Date)
if animated {
UIView.transition(with: cell.contentView, duration: 0.3, options: .transitionCrossDissolve, animations: {
cell.textLabel?.text = dateString
}, completion: nil)
} else {
cell.textLabel?.text = dateString
}
}
riutilizzare il metodo configure qui senza animazione:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: CellReuseIdentifier, for: indexPath)
let note = fetchedResultsController.object(at: indexPath)
configure(cell: cell, note: note)
return cell
}
Se si dispone di una cella più complicata (sottoclasse), potresti probabilmente spostare il metodo configure nel codice della sottoclasse. La parte importante è avere un metodo per aggiornare i dati della cella con l'animazione opzionale.
Questo sembra essere il modo migliore. Strano che il richiamo di 'reloadData' all'interno del blocco di aggiornamento annulli le animazioni. – devios1