Ответ 1
ОК, я понял это. Как вы говорите, проблема связана с автоматическими размерами ячеек. Я использовал два трюка, чтобы заставить все работать (мой код в Swift, но его нужно легко перевести обратно в ObjC):
1) Дождитесь завершения анимации таблицы, прежде чем предпринимать дальнейшие действия. Это можно сделать, включив код, который обновляет таблицу внутри блока между CATransaction.begin()
и CATransaction.commit()
. Я установил блок завершения в CATransaction - этот код будет запущен после завершения анимации.
2) Принудите представление таблицы для отображения ячейки перед прокруткой вниз. Я делаю это, увеличивая таблицу contentOffset
на небольшую сумму. Это приводит к тому, что вновь вставленная ячейка будет удалена, и вычисляется ее высота. Как только этот прокрутка закончена (я жду, пока она закончит использование метода (1) выше), я, наконец, звоню tableView.scrollToRowAtIndexPath
.
Здесь код:
override func viewDidLoad()
{
super.viewDidLoad()
// Use auto-sizing for rows
tableView.estimatedRowHeight = 40
tableView.rowHeight = UITableViewAutomaticDimension
tableView.dataSource = self
}
func chatManager(chatManager: ChatManager, didAddMessage message: ChatMessage)
{
messages.append(message)
let indexPathToInsert = NSIndexPath(forRow: messages.count-1, inSection: 0)
CATransaction.begin()
CATransaction.setCompletionBlock({ () -> Void in
// This block runs after the animations between CATransaction.begin
// and CATransaction.commit are finished.
self.scrollToLastMessage()
})
tableView.beginUpdates()
tableView.insertRowsAtIndexPaths([indexPathToInsert], withRowAnimation: .Bottom)
tableView.endUpdates()
CATransaction.commit()
}
func scrollToLastMessage()
{
let bottomRow = tableView.numberOfRowsInSection(0) - 1
let bottomMessageIndex = NSIndexPath(forRow: bottomRow, inSection: 0)
guard messages.count > 0
else { return }
CATransaction.begin()
CATransaction.setCompletionBlock({ () -> Void in
// Now we can scroll to the last row!
self.tableView.scrollToRowAtIndexPath(bottomMessageIndex, atScrollPosition: .Bottom, animated: true)
})
// scroll down by 1 point: this causes the newly added cell to be dequeued and rendered.
let contentOffset = tableView.contentOffset.y
let newContentOffset = CGPointMake(0, contentOffset + 1)
tableView.setContentOffset(newContentOffset, animated: true)
CATransaction.commit()
}