CGPoint offset = [_table contentOffset];
[_table reloadData];
[_table setContentOffset:offset animated:NO]; //unuseful
// __block UITableView *tableBlock = _t
fileprivate var heightDictionary: [IndexPath: CGFloat] = [:]
override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
heightDictionary[indexPath] = cell.frame.size.height
}
override func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
let height = heightDictionary[indexPath]
return height ?? UITableViewAutomaticDimension
}
This method should be called instead of reloadData
. This can fit for specific cases.
public func reloadDataAndKeepOffset() {
// stop scrolling
setContentOffset(contentOffset, animated: false)
// calculate the offset and reloadData
let beforeContentSize = contentSize
reloadData()
layoutIfNeeded()
let afterContentSize = contentSize
// reset the contentOffset after data is updated
let newOffset = CGPoint(
x: contentOffset.x + (afterContentSize.width - beforeContentSize.width),
y: contentOffset.y + (afterContentSize.height - beforeContentSize.height))
setContentOffset(newOffset, animated: false)
}
By default, reloadData keeps the contentOffset. However, it could be updated if you do have inaccurate estimatedRowHeight values.
I was having trouble with this because I mess with cell sizing in my cellForRowAtIndexPath method. I noticed that the sizing information was off after doing reloadData, so I realized I needed to force it to layout immediately before setting the content offset back.
CGPoint offset = tableView.contentOffset;
[tableView.messageTable reloadData];
[tableView layoutIfNeeded]; // Force layout so things are updated before resetting the contentOffset.
[tableView setContentOffset:offset];
If you implement estimatedHeightForRowAtIndexPath
method and your estimate is not right, you will possible get into this situation.
To solve this, you can return a large height that bigger than every cell height in your tableView, like this:
- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath {
return 800.f; // if 800 is bigger than every possible value of your cell height.
}
For it works fine
[tView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]
atScrollPosition:UITableViewScrollPositionTop
animated:NO];
This is working 100%
change the tableView.reloadData()
into
tableView.reloadRows(at: tableView!.indexPathsForVisibleRows!, with: .none)