I have a _TableView
with items , and I want to set automatic refresh,and I don\'t want it to scroll on refresh , lets say user scrolled 2 pages down , and the refre
When you want to reload you have to
self.tableView.reloadData()
self.tableView.layoutIfNeeded()
and also use this UITableViewDelegate
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return 'your maximum cell's height'
}
and your tableView will remain on the previous scroll position without scrolling
SWIFT 3
let contentOffset = self.tableView.contentOffset
self.tableView.reloadData()
self.tableView.layoutIfNeeded()
self.tableView.setContentOffset(contentOffset, animated: false)
This is error of iOS8 when using UITableViewAutomatic Dimension. We need store the content offset of table, reload table, force layout and set contenOffset back.
CGPoint contentOffset = self.tableView.contentOffset;
[self.tableView reloadData];
[self.tableView layoutIfNeeded];
[self.tableView setContentOffset:contentOffset];
Just set estimatedRowHeight
to maximum possible value.
self.tableView.estimatedRowHeight = 1000
self.tableView.estimatedSectionFooterHeight = 100.0
self.tableView.estimatedSectionHeaderHeight = 500.0
That's it!!
Please do not use FLT_MAX, DBL_MAX
value. May be it will crash your app.
I'm doing it this way:
messages.insertContentsOf(incomingMsgs.reverse(), at: 0)
table.reloadData()
// This is for the first load, first 20 messages, scroll to bottom
if (messages.count <= 20) {
let indexToScroll = NSIndexPath(forRow: saferSelf.messages.count - 1, inSection: 0)
table.scrollToRowAtIndexPath(indexToScroll, atScrollPosition: .Top , animated: false)
}
// This is to reload older messages on top of tableview
else {
let indexToScroll = NSIndexPath(forRow: incomingMsgs.count, inSection: 0)
table.scrollToRowAtIndexPath(indexToScroll, atScrollPosition: .Top , animated: false)
// Remove the refreshControl.height + tableHeader.height from the offset so the content remain where it was before reload
let theRightOffset = CGPointMake(0, table.contentOffset.y - refreshControl.frame.height - table.headeView.frame.height)
table.setContentOffset(theRightOffset, animated: false)
}
...also, since I use dynamic cell height, to avoid some weirdness, the estimation is cached:
var heightAtIndexPath = [NSIndexPath: CGFloat]()
func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return heightAtIndexPath[indexPath] ?? UITableViewAutomaticDimension
}
func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
heightAtIndexPath[indexPath] = cell.frame.height
}
For Swift 3+:
You need to save the current offset of the UITableView
, then reload and then set the offset back on the UITableView
.
I have created this function for this purpose:
func reload(tableView: UITableView) {
let contentOffset = tableView.contentOffset
tableView.reloadData()
tableView.layoutIfNeeded()
tableView.setContentOffset(contentOffset, animated: false)
}
Simply call it with: reload(tableView: self.tableView)
Use Extension
create UITableViewExtensions.swift
and add following:
extension UITableView {
func reloadDataWithoutScroll() {
let offset = contentOffset
reloadData()
layoutIfNeeded()
setContentOffset(offset, animated: false)
}
}