调用-reloadData后如何保持UITableView的contentoffset

CGPoint offset = [_table contentOffset]; [_table reloadData]; [_table setContentOffset:offset animated:NO]; //unuseful // __block UITableView *tableBlock = _table; // [self performBlock:^(id sender) { // [tableBlock setContentOffset:offset]; // } afterDelay:2]; 

我知道在reloadData之后没有调用委托方法。 而且afterDelay:2可能太短或太长,那我该如何实现呢?

我的英文不好,我希望你能理解…

我最近正在使用reloadDatareloadData不会更改contentOffset或滚动表视图。 如果偏移量小于新的数据量,它实际上保持不变。

我遇到了麻烦,因为我在cellForRowAtIndexPath方法中弄乱了单元格大小。 我注意到在做reloadData之后,尺寸信息是closures的,所以我意识到在设置内容偏移量之前,我需要强制它进行布局。

 CGPoint offset = tableView.contentOffset; [tableView.messageTable reloadData]; [tableView layoutIfNeeded]; // Force layout so things are updated before resetting the contentOffset. [tableView setContentOffset:offset]; 

在tableView上调用reloadData不会改变内容的偏移量。 但是,如果您使用iOS 8中引入的UITableViewAutomaticDimension ,则可能会出现问题。

在使用UITableViewAutomaticDimension ,需要编写委托方法tableView: estimatedHeightForRowAtIndexPath:并返回UITableViewAutomaticDimensiontableView: heightForRowAtIndexPath:这也返回相同的值。

对我来说,我在使用这个时遇到了iOS 8的问题。 这是因为方法estimatedHeightForRowAtIndexPath:方法是返回不准确的值,即使我使用UITableViewAutomaticDimension 。 这是iOS 8的问题,因为iOS 9设备没有问题。

我通过使用字典存储单元格高度的值并返回它解决了这个问题。 这就是我所做的。

 - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath { NSNumber *key = @(indexPath.row); NSNumber *height = @(cell.frame.size.height); [self.cellHeightsDictionary setObject:height forKey:key]; } - (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath { NSNumber *key = @(indexPath.row); NSNumber *height = [self.cellHeightsDictionary objectForKey:key]; if (height) { return height.doubleValue; } return UITableViewAutomaticDimension; } - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { return UITableViewAutomaticDimension; } 

是否存在高度的检查是第一次页面加载。

默认情况下,reloadData保留contentOffset。 但是,如果您的估算的RoughHeight值不准确,则可能会更新。

天行者的Swift 3变体的回答:

 fileprivate var heightDictionary: [Int : CGFloat] = [:] func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) { heightDictionary[indexPath.row] = cell.frame.size.height } func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat { let height = heightDictionary[indexPath.row] return height ?? UITableViewAutomaticDimension } 

如果你在你的dataSource数组的开头插入数据,你需要像这样改变contentOffsetSwift 3+

 func prepareReloadData() { let previousContentHeight = tableView.contentSize.height let previousContentOffset = tableView.contentOffset.y tableView.reloadData() let currentContentHeight = tableView.contentSize.height - previousContentHeight + previousContentOffset tableView.contentOffset = CGPoint(x: 0, y: currentContentHeight) } 

我有同样的问题,但没有任何答案build议在这里工作。 这是我如何解决它。 子类UITableView和重写layoutSubviews方法是这样的:

 override func layoutSubviews() { let offset = contentOffset super.layoutSubviews() contentOffset = offset } 

@Meharoof Najeeb的显示最好的解决方法,估计细胞高度的问题。 但有时问题在不同的地方。
有时这个问题会在表格视图的contentInsets中出现。 如果在tableView在屏幕上不可见的情况下重新加载数据,那么在屏幕上出现表格视图后,可能会遇到错误的偏移量。
发生这种情况是因为UIViewController可以控制插入,如果他的scrollView然后scrollView看起来允许scrollView下面透明navigationBar和statusBar。
我在iOS 9.1中遇到过这种情况

这对我有用Swift 3

 self.table.reloadData() self.table.scrollToRow(at: IndexPath(row: 0, section: 0), at: UITableViewScrollPosition.top, animated: true) 

这是工作100%

 change the tableView.reloadData() 

 tableView.reloadRows(at: tableView!.indexPathsForVisibleRows!, with: .none) 

因为它工作正常

 [tView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:NO];