У меня возникли реальные проблемы с пакетным обновлением / анимацией UITableViewCell.
Я не могу перезагрузить ячейку, когда перед ней перемещается другая ячейка.
Не уверен, что я делаю что-то не так или есть ли ошибка в git в UITableView.
Пример
Учитывая начальный набор данных ячейки, упорядоченный следующим образом. ..
anna [19]
bob [16]
chloe [13]
при обновлении данных ячейки до ...
bob [17]
chloe [13]
anna [19]
... и попытке анимировать изменение в пакете с помощью (псевдо-кода) ...
moveRow(at: 0, to: 2) // to move "anna" from first to last position
reloadRows(at: [1]) // to reload "bob" since its number changed from 16 to 17
... перезагружена неправильная ячейка, и я получаю ...
chloe [13]
chloe [13]
anna [19]
Результирующая анимация
Пример кода
class TableViewController: UITableViewController {
private var data: [String] = [
"anna [19]",
"bob [16]",
"chloe [13]",
]
override func viewDidAppear(_ animated: Bool) {
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
print("---- PERFORMING BATCH UPDATES ----")
self.data = [
"bob [17]", // this row has had its value updated
"chloe [13]",
"anna [19]", // this row has moved from its previous position of index 0
]
self.tableView.performBatchUpdates({
// Reload "bob" row
let reloadIndexPath = IndexPath(row: 1, section: 0)
self.tableView.reloadRows(at: [reloadIndexPath], with: .automatic)
// Move "anna" row from index 0 to index 2
let fromIndexPath = IndexPath(row: 0, section: 0)
let toIndexPath = IndexPath(row: 2, section: 0)
self.tableView.moveRow(at: fromIndexPath, to: toIndexPath)
})
}
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return data.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
let value = data[indexPath.row]
cell.textLabel?.text = value
print("DRAWING cell at indexPath: \(indexPath), value: \(value)")
return cell
}
}
Результирующий вывод на консоль
DRAWING cell at indexPath: [0, 0], value: anna [19]
DRAWING cell at indexPath: [0, 1], value: bob [16]
DRAWING cell at indexPath: [0, 2], value: chloe [13]
---- PERFORMING BATCH UPDATES ----
DRAWING cell at indexPath: [0, 1], value: chloe [13]
Чем этот вопрос не является
Я знаю, что Существуют ограничения для пакетных обновлений и невозможность перемещения и перезагрузки одной и той же ячейки 1039 * в одной партии без получения attempt to perform a delete and a move from the same index path
cra sh (ссылки здесь & здесь )
ОДНАКО это НЕ то, что здесь происходит. Эта проблема перемещает одну ячейку и перезагружает другую (которая явно не перемещается).
Для вызова reloadRows
я намеренно использую индекс 1, исходную позицию ячейки, а не 0, его окончательная позиция, потому что именно этого требует официальная документация Apple . Это также подтверждается тем фактом, что вызов reloadRows
с индексом 0 вместо этого приводит к attempt to perform a delete and a move from the same index path
cra sh.
Некоторые дополнительные замечания
Из журнала консоли видно, что tableView(_:,cellForRowAt:)
вызывается как часть обновления, но перезагружается неправильная ячейка
Изменение порядка вызовов moveRow
и reloadRows
не имеет значения
Использование beingUpdates()
/ endUpdates
в отличие от performBatchUpdates
не имеет значения
Пожалуйста, помогите!
DifferenceKit
Ошибка, кажется, возникает и в DifferenceKit. Я обновил их демо-приложение, чтобы имитировать ту же ситуацию, и в результате получается анимация.
Код с проблемой доступен здесь ...
https://github.com/OliverPearmain/DifferenceKit/tree/reload-with-move-bug
И я поднял проблему с DifferenceKit здесь ...
https://github.com/ra1028/DifferenceKit/issues/98