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
This code will prevent unnecessary animation and maintain the scroll view's content offset, it worked fine for me.
let lastScrollOffset = tableView.contentOffset
tableView.beginUpdates()
tableView.reloadData()
tableView.endUpdates()
tableView.layer.removeAllAnimations()
tableView.setContentOffset(lastScrollOffset, animated: false)
I am showing if only one row is being added. You can extend it to multiple rows.
// dataArray is your data Source object
[dataArray insertObject:name atIndex:0];
CGPoint contentOffset = self.tableView.contentOffset;
contentOffset.y += [self tableView:self.tableView heightForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]];
[self.tableView reloadData];
[self.tableView setContentOffset:contentOffset];
But for this to work you need to have defined - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
the method. Or else, you can directly give your tableview row height if it is constant.
In iOS 12.x
, using Xcode 10.2.1
, an easier option is.
UIView.performWithoutAnimation {
let loc = tableView.contentOffset
tableView.reloadRows(at: [indexPath], with: .none)
tableView.contentOffset = loc
}
This works better than following; it shakes at times when the row is not fully visible.
let contentOffset = self.tableView.contentOffset
self.tableView.reloadData()
self.tableView.layoutIfNeeded()
self.tableView.setContentOffset(contentOffset, animated: false)
i wrote something that works perfect for me:
extension UIScrollView {
func reloadDataAndKeepContentOffsetInPlace(reloadData:(() -> Void)) {
let currentContentHeight = contentSize.height
if currentContentHeight == .zero {
reloadData()
return
}
reloadData()
layoutIfNeeded()
let newContentHeight = self.contentSize.height
DispatchQueue.main.async {
var contentOffset = self.contentOffset
contentOffset.y += newContentHeight - currentContentHeight
self.setContentOffset(contentOffset, animated: false)
}
}
}
use like this:
self.reloadSomeData()
collectionView.reloadDataAndKeepContentOffsetInPlace { [weak self] in
guard let self = self else { return }
self.collectionView.reloadData()
}
try to replace
reloadData
with
tableView.reloadRows
(at: tableView!.indexPathsForVisibleRows!, with: .none
),
but you should be care about no cells
, if no cells
, this method should cause crash.
Swift 4.2 : Simple Solution
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.estimatedRowHeight = 0
self.tableView.estimatedSectionHeaderHeight = 0
self.tableView.estimatedSectionFooterHeight = 0
}
//And then simply update(insert, reloadSections, delete etc) your tableView or reload
tableView.reloadData()
//or
UIView.performWithoutAnimation {
tableView.beginUpdates()
.....
tableView.endUpdates()
}