I have a UITableView
that is populated with cells with dynamic height. I would like the table to scroll to the bottom when the view controller is pushed from vi
Using Swift 5 you can also do this after each reload:
DispatchQueue.main.async {
let index = IndexPath(row: self.itens.count-1, section: 0)
self.tableView.scrollToRow(at: index, at: .bottom, animated: true)
}
You can use this one also:-
tableView.scrollRectToVisible(CGRect(x: 0, y: tableView.contentSize.height, width: 1, height: 1), animated: true)
Works in Swift 4+ :
self.tableView.reloadData()
let indexPath = NSIndexPath(row: self.yourDataArray.count-1, section: 0)
self.tableView.scrollToRow(at: indexPath as IndexPath, at: .bottom, animated: true)
This is a function that contains the completion closer:
func reloadAndScrollToTop(completion: @escaping () -> Void) {
self.tableView.reload()
completion()
}
And use:
self.reloadAndScrollToTop(completion: {
tableView.scrollToRow(at: indexPath, at: .top, animated: true))
})
The tableView.scrollTo ...
line will be executed after all table cells have been safely loaded.
When you push the viewcontroller having the tableview you should scrollTo the specified indexPath only after your Tableview is finished reloading.
yourTableview.reloadData()
dispatch_async(dispatch_get_main_queue(), { () -> Void in
let indexPath = NSIndexPath(forRow: commentArray.count-1, inSection: 0)
tableView.scrollToRowAtIndexPath(indexPath, atScrollPosition: .Bottom, animated: true)
})
The reason for putting the method inside the dispatch_async is once you execute reloadData the next line will get executed immediately and then reloading will happen in main thread. So to know when the tableview gets finished(After all cellforrowindex is finished) we use GCD here. Basically there is no delegate in tableview will tell that the tableview has finished reloading.
Works in Swift 3+ :
self.tableView.setContentOffset(CGPoint(x: 0, y: self.tableView.contentSize.height - UIScreen.main.bounds.height), animated: true)