Ни один из ответов здесь действительно не работал для меня, поэтому я нашел свое решение.Идея состоит в том, что когда вы тянете вниз, чтобы обновить табличное представление (или загрузить его асинхронно с новыми данными), новые ячейки должны молча приходить и сидеть поверх табличного представления, не нарушая текущего смещения пользователя.Итак, вот решение, которое работает (в значительной степени, с предостережением )
var indexpathsToReload: [IndexPath] = [] //this should contain the new indexPaths
var height: CGFloat = 0.0
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 1) {
UIView.performWithoutAnimation {
self.tableview.reloadSections(NSIndexSet(index: 0) as IndexSet, with: .none)
self.tableview.layoutIfNeeded()
indexpathsToReload.forEach({ (idx) in
height += self.feed.rectForRow(at: idx).height
})
let afterContentOffset = self.tableview.contentOffset
let newContentOffset = CGPoint(x: afterContentOffset.x, y: afterContentOffset.y + height)
self.tableview.setContentOffset(newContentOffset, animated: false)
}
}
CAVEAT (ПРЕДУПРЕЖДЕНИЕ) Этот метод не будет работать, если ваш просмотр таблицы не«полный», то есть в нем всего пара ячеек.В этом случае вам также необходимо увеличить contentSize
таблицы вместе с contentOffset
.Я обновлю этот ответ, как только угадаю его.
ОБЪЯСНЕНИЕ : По сути, нам нужно установить contentOffset
tableView
в положение, в котором он находился до перезагрузки,Для этого мы просто вычисляем общую высоту всех новых ячеек, которые были добавлены, используя предварительно заполненный массив indexPath
(может быть подготовлен, когда вы получите новые данные и добавите их в источник данных), это indexPaths
дляновые клетки.Затем мы используем общую высоту всех этих новых ячеек, используя rectForRow(at: indexPath)
, и устанавливаем ее как y
положение contentOffset
tableView
после перезагрузки.DispatchQueue.main.asyncAfter
не является необходимым, но я поместил его туда, потому что мне просто нужно дать столу некоторое время, чтобы вернуться в исходное положение, так как я делаю это по принципу «тянуть, чтобы обновить».Также обратите внимание, что в моем случае значение afterContentOffset.y
всегда равно 0
, поэтому вместо него можно было бы жестко указать 0
.