#swift #uitableview #asynchronous
#swift #uitableview #асинхронный
Вопрос:
У меня есть список любимых фильмов. В ячейке таблицы есть кнопка для удаления фильма из списка избранного. Итак, я хочу анимировать его с помощью TableView.deleteRows. Но если я удалю строку из верхней части экрана, другие строки поднимутся вверх. Это нормально, но когда я удалял строку из верхней части экрана, другие ячейки, которые уже показаны в списке, не обновляли indexPath. Я назначаю метод asyncAfter для TableView.reloadData для решения проблемы, но я думаю, что это может привести к сбою на стороне операционной системы. Потому что я заставил основной поток перезагрузить данные после задержки. Действительно ли это проблема для ОС и что мне делать?
Пример проблемы:
Если я удалю фильм с индексом 0, все фильмы будут увеличиваться. Таким образом, перед удалением у 1 индексного фильма должен быть индекс 0, но это не так. Если я попытался удалить новый фильм с индексом 0, он удаляет другой фильм.
Пример работы без TableView.reloadData()
Вот мой код // Это работает, но я думаю, что проблема в asyncAfter
cell.deleteButtonActionBlock = {
FavouritesHandler.shared.deleteMovie(movie)
self.tableView.deleteRows(at: [indexPath], with: .automatic)
DispatchQueue.main.asyncAfter(deadline: .now() 0.3) {
self.tableView.reloadData()
}
}
Комментарии:
1. Вы ранее удаляли элемент из массива datasource
tableView.deleteRows
?2. @Jithin да, favoriteshandler.shared. deleteMovie (фильм) удаление фильма из массива
3. Я предполагаю, что что-то не так в том, как вы фиксируете путь к индексу.
4. @vadian этот фрагмент в TableView cellForRowAt использует indexPath, я так не думаю
5. Я делаю, это именно проблема. Пожалуйста, посмотрите мой ответ.
Ответ №1:
Вы не должны использовать записанный путь индекса, если ячейки могут быть удалены, вставлены или перемещены.
В пользовательской ячейке объявить закрытие
var deleteButtonActionBlock : ((UITableViewCell) -> Void)?
и вызвать его
deleteButtonActionBlock?(self)
В cellForRow
получите фактический путь к индексу для ячейки
cell.deleteButtonActionBlock = { aCell in
let actualIndexPath = tableView.indexPath(for: aCell)!
FavouritesHandler.shared.deleteMovie(movie)
tableView.deleteRows(at: [actualIndexPath], with: .automatic)
}
Не требуется (уродливая) задержка и (бессмысленная) перезагрузка.
Пожалуйста, обратите внимание также, что я удалил self
в delete
строке, потому что экземпляр TableView доступен в качестве параметра метода.
Комментарии:
1. Большое вам спасибо. Не могли бы вы, пожалуйста, объяснить, почему захваченный indexPath не работает должным образом? Это моя вторая неделя в Swift 🙂
2. Да, термин » захват » содержит объяснение. В тот момент, когда вы назначаете закрытие, путь к индексу заморожен и больше не изменяется. Это приводит к неожиданному поведению.
3. Если я не ошибаюсь, при использовании cellForRowAt indexPath обновляется при изменении ячейки. Но с использованием closure я передал его, когда я использую deleteButton. Я действительно ценю вас. Большое спасибо за вашу помощь.
4.
cellForRow
не вызывается снова послеdelete-/insertRows