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
这种黑客可能太短或太长,所以我该如何实现呢?
答案 0 :(得分:99)
我遇到了麻烦,因为我在cellForRowAtIndexPath方法中搞乱了细胞大小。我注意到在执行reloadData之后调整大小信息已经关闭,所以我意识到我需要在设置内容偏移之前立即强制它进行布局。
CGPoint offset = tableView.contentOffset;
[tableView.messageTable reloadData];
[tableView layoutIfNeeded]; // Force layout so things are updated before resetting the contentOffset.
[tableView setContentOffset:offset];
答案 1 :(得分:84)
在tableView上调用reloadData
不会更改内容偏移量。但是,如果您使用的是iOS 8中引入的UITableViewAutomaticDimension
,则可能会出现问题。
使用UITableViewAutomaticDimension
时,需要编写委托方法tableView: estimatedHeightForRowAtIndexPath:
并返回UITableViewAutomaticDimension
以及tableView: 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;
}
检查是否存在高度是第一次加载页面。
答案 2 :(得分:25)
fileprivate var heightDictionary: [Int : CGFloat] = [:]
override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
heightDictionary[indexPath.row] = cell.frame.size.height
}
override func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
let height = heightDictionary[indexPath.row]
return height ?? UITableViewAutomaticDimension
}
应该调用此方法而不是reloadData
。这适用于特定情况。
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)
}
答案 3 :(得分:21)
默认情况下,reloadData会保留contentOffset。但是,如果您确实有不准确的estimatedRowHeight值,则可以更新它。
答案 4 :(得分:15)
答案 5 :(得分:13)
我最近使用reloadData
- reloadData
并未更改contentOffset
或滚动表格视图。如果偏移量小于新的数据量,它实际上保持不变。
答案 6 :(得分:6)
如果在dataSource数组的开头插入数据,则需要像这样更改Observables
:
Swift 3 +
contentOffset
答案 7 :(得分:6)
如果实施estimatedHeightForRowAtIndexPath
方法并且您的估计不正确,则可能会遇到这种情况。
要解决此问题,您可以返回一个较大的高度,该高度大于tableView中每个单元格的高度,如下所示:
- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath {
return 800.f; // if 800 is bigger than every possible value of your cell height.
}
答案 8 :(得分:2)
我遇到了同样的问题,但这里没有提出任何答案。这是我如何解决它。子类UITableView
并覆盖layoutSubviews
方法,如下所示:
override func layoutSubviews() {
let offset = contentOffset
super.layoutSubviews()
contentOffset = offset
}
答案 9 :(得分:2)
@ Skywalker的回答显示了估计细胞高度问题的最佳解决方法。但有时在不同的地方会出现问题
有时问题会在表视图的contentInsets中出现。如果在屏幕上看不到tableView时重新加载数据,则在屏幕上出现表格视图后,您可能会面对错误的偏移。
这是因为UIViewController可以控制插件,如果他的scrollView在scrollView出现时允许将scrollView放在透明navigationBar和statusBar下面。
我在iOS 9.1中遇到过这种行为
答案 10 :(得分:1)
马特的上述回答使我意识到estimatedRowHeight
一定是一个问题。
因此,正如一些人指出的那样,reloadData
不应修改contentOffset
,因此在设置rowHeight = UITableView.automaticDimension
时,只是要确保设置正确的estimatedRowHeight
。
如果estimatedRowHeight
比估计的UITableView
短,它将尝试固定高度,并且滚动行为将出现,但前提是出现高度问题的单元格可见。换句话说,请确保您的estimatedRowHeight
设置正确。
我希望这可以帮助其他人。
答案 11 :(得分:-3)
这是100%的工作
change the tableView.reloadData()
到
tableView.reloadRows(at: tableView!.indexPathsForVisibleRows!, with: .none)
答案 12 :(得分:-4)
因为它工作正常
[tView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]
atScrollPosition:UITableViewScrollPositionTop
animated:NO];