Realm всегда будет отправлять изменения модификации при обновлении объекта, независимо от того, изменились ли данные, но это не значит, что мы не можем решить проблему и даже реализовать некоторые приятные улучшения.
Вместо перезагрузки всего представления таблицы, когда наблюдаются изменения, мы хотим вставить, удалить или перезагрузить ячейки вручную.Я написал расширение для этого в табличном представлении.
import UIKit
// RealmDiff is just a lightweight struct to make passing the changes around cleaner
// public struct RealmDiff {
// let deletions: [Int]
// let insertions: [Int]
// let modifications: [Int]
//}
extension UITableView {
func reload(section: Int = 0, with diff: RealmDiff?, update: ((UITableViewCell, IndexPath) -> Void)? = nil) {
guard let diff = diff else {
reloadData()
return
}
beginUpdates()
insertRows(at: diff.insertions.map({ IndexPath(row: $0, section: section) }), with: .automatic)
deleteRows(at: diff.deletions.map({ IndexPath(row: $0, section: section) }), with: .automatic)
guard update != nil else {
reloadRows(at: diff.modifications.map({ IndexPath(row: $0, section: section) }), with: .fade)
endUpdates()
return
}
endUpdates()
let indexPaths = diff.modifications
.map ({ IndexPath(row: $0, section: 0) })
.filter { indexPathsForVisibleRows?.contains($0) ?? false }
indexPaths.forEach {
if let cell = cellForRow(at: $0) {
update?(cell, $0)
}
}
}
}
По умолчанию это по-прежнему будет обменивать все ячейки, что, вероятно, будет вызывать скачки в табличном представлении в зависимости от вашей реализации макета.Но мы также можем передать закрытие, чтобы вручную изменить данные в ячейке.Вот пример используемого расширения:
tableView.reload(with: diff) { [weak self] cell, indexPath in
if let cell = cell as? MyCellClass {
MyCellClass.configure(cell: cell, with: myDataSourceDataArray[indexPath.row], delegate: self)
}
}
Таким образом, вы используете одну и ту же ячейку, и перезагрузка не требуется.Я считаю, что этот метод работает очень хорошо и его можно использовать многократно.