UITableView scrollToRowAtIndexPath在iOS 7上使用estimatedRowHeight滚动到错误的偏移量

时间:2014-01-02 21:55:21

标签: iphone uitableview ios7

我正在使用iOS 7中UITableView的estimatedRowHeight方法,它非常适合快速加载具有5000行可变高度的UITableView。

我的UITableView包含50个部分。每个部分有100行,高度可变。 在开始时我使用estimatedRowHeight进行快速加载,但在此之后,当我调用scrollToRowAtIndexPath时,我的UITableView滚动到错误的偏移量。我可以理解为什么会这样,因为它有一个estimatedRowHeight,直到我滚动整个表格并在heightForRowAtIndexPath委托方法中设置了正确的单元格高度。

任何解决方案?

9 个答案:

答案 0 :(得分:7)

不幸的是,在使用如此低的值的代码中使用estimatedRowHeight时会出现此问题。当您scrollToRowAtIndexPath时,它不会主动计算正确的大小。根本原因是,如果您从第1节滚动到第2节,它可以实时计算正确的位置和单元格的estimatedRowHeight,如果它是一个相对较新的设备。任何较旧的设备都会被瘫痪,例如,如果你必须处理5000个细胞,那么任何新的设备也会如此。

解决问题的一个可能方法是增加estimatedRowHeight常数,这样设备就不必做太多的工作。

答案 1 :(得分:2)

当调用scrollToRowAtIndexPath时,不计算所有单元格的高度b / w当前位置和目标偏移。只有其中一些是。

相反,UITableView使用estimatedRowHeight来计算导致错误偏移的目标偏移量。

我面临同样的问题,我发现了一个小技巧(我不太喜欢),只能在初始relaodData之后计算一次精确的细胞高度。我在下面插入两行:

tableView.reloadData()

// only for the initial reloadData

let numSections = tableView.numberOfSections
let numRowsInLastSection = tableView.numberOfRowsInSection(numSections-1)

// scrolls to the last row in the tableView
tableView.scrollToRowAtIndexPath(NSIndexPath(forRow: numRows-1, inSection: numSections-1), atScrollPosition: .Bottom, animated: false)

// back again to the original position(which is 0 for this is only called right after the initial reloadData)
tableView.scrollToRowAtIndexPath(NSIndexPath(forRow: 0, inSection: 0), atScrollPosition: .Top, animated: false)

这会导致tableView出现在屏幕上较晚,但我认为在tableView出现后它可以接受而不是冻结UI。当你在开始时调用API时会更好,因为它感觉网络有点延迟,而不是UI延迟。

在此之后,tableView跳转到单元格的准确位置。

是的,我也不喜欢这个解决方案:|

编辑:

我这样做的唯一原因是通过调用cellForRowAtIndexPath:来计算实际的行高,但是我发现在通过委托方法estimatedHeightForRowAtIndexPath:为每一行提供正确的estimatedHeight时,而不是给{UITableView.estimatedRowHeight提供静态值1}}解决了这个问题。

我最终做的是将willDisplayCell:forRowAtIndexPath:行的高度缓存到磁盘,并在estimatedHeightForRowAtIndexPath:上使用该值。

通过这样做,所有行的estimatedHeightForRowAtIndexPath:在开始时被调用,而scrollToRowAtIndexPath效果很好。

答案 2 :(得分:1)

这不是最漂亮的解决方案,但我使用了解决这个问题的解决方法。始终将estimatedRowHeight更新为最高的计算单元格,然后使用以下内容:

  1. 滚动tableView的内容以抵消零。
  2. 通过调用scrollToRowAtIndexPath来索引路径零来完成。

    [self.tableView setContentOffset:CGPointZero animated:YES];
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        [self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]
                              atScrollPosition:UITableViewScrollPositionTop
                                      animated:YES];
    });
    
  3. 结果tableView应该非常顺利地滚动到顶部。

答案 3 :(得分:1)

我的解决方案是设置estimatedRowHeight to 0

答案 4 :(得分:1)

这解决了我的问题

let oldContentSize = tableView.contentSize
tableView.scrollToRow(at: indexPath, at: .top, animated: true)
// Called again when tableView contentSize change
if !tableView.contentSize.equalTo(oldContentSize) {
    tableView.scrollToRow(at: indexPath, at: .top, animated: true)
}

答案 5 :(得分:0)

仍然没有可靠的解决方案,但对我来说,执行一个没有动画的滚动是可以接受的,因为它滚动到具有正确偏移的预期单元格,尽管http://www.openradar.me/20829131中提到了什么。 / p>

self.tableView.scrollToRowAtIndexPath(indexPath, atScrollPosition:.Top, animated: false)

答案 6 :(得分:0)

在视图由系统布局后似乎可以工作。我正在VC的viewDidAppear中调用scrollToRowAtIndexPath并获得正确的结果。当然,这不是很漂亮,因为它在视图已经可见时滚动...

答案 7 :(得分:0)

尝试在返回单元格之前在-cellForRowAtIndexPath:中添加此代码

[cell layoutIfNeeded]

答案 8 :(得分:0)

我的错误是因为“ atScrollPosition”设置为UITableViewScrollPositionNone-将其更改为UITableViewScrollPositionMiddle,它应该可以正常工作