Tôi đã gặp sự cố tương tự khi sắp xếp theo "dateModified" nhưng tôi cũng hiển thị thuộc tính đó trên nhãn của ô. Cả hai "di chuyển" và "cập nhật" được yêu cầu. "di chuyển" chỉ được gọi để ô chính xác được đưa lên đầu danh sách, nhưng văn bản nhãn không cập nhật.
Giải pháp của tôi cho UITableViewCell đơn giản.
Trước tiên, bạn thực hiện cuộc gọi .move như bình thường. Trực tiếp sau khi bạn thực hiện cuộc gọi đến một phương pháp cấu hình tùy chỉnh - có trách nhiệm tạo hoạt ảnh cho "cập nhật" trên ô.
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)
}
}
Phương pháp cấu hình trông như thế này (lưu ý hoạt hình là không bắt buộc):
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
}
}
Tái sử dụng các phương pháp cấu hình ở đây mà không ảnh động:
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
}
Nếu bạn có một tế bào phức tạp hơn (subclass), bạn có thể di chuyển phương thức cấu hình tới mã lớp con. Phần quan trọng là có một phương pháp để cập nhật dữ liệu ô với hoạt ảnh tùy chọn.
Điều này dường như là cách tốt nhất. Điều lạ lùng khi gọi 'reloadData' từ bên trong khối cập nhật sẽ hủy hoạt ảnh. – devios1