较为优雅地解决UITableView在reloadData时跳动的问题

在开发中也遇到了UITableView刷新跳动的问题,搜索一下解决方案,但是基本都是如下的做法

    _tableView.estimatedRowHeight = 0;
    _tableView.estimatedSectionHeaderHeight = 0;
    _tableView.estimatedSectionFooterHeight = 0;

这一方案实际上是禁用了自动计算,从而使UITableView刷新不再跳动。

但是这是一个带有误伤的方案。estimatedRowHeight = 0 同时禁用了方便的AutomaticDimension。
对于手动计算高度的方式,这样是没什么问题的,但是如果用到了AutomaticDimension,怎么办呢。

一个简单有效的方案,就是缓存高度。

- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSNumber *heightNumber = [self.cellHeightDict objectForKey:indexPath];
    CGFloat height = 50;
    if(heightNumber)
    {
        height = heightNumber.floatValue;
    }
    return height;
}

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
    CGFloat cellHeight = cell.frame.size.height;
    [self.cellHeightDict setObject:@(cellHeight) forKey:indexPath];
}

方案的本质是提供准确的estimatedRowHeight使得UITableView的contentSize计算准确,从而不会产生所谓的跳动现象。
这其实也揭示了一点,estimatedRowHeight其实并非应该随意设置,而是应该尽可能的准确,日常使用可能会忽略这一点,所以会有许多奇怪的bug出现,这些都是没有准确使用的结果。(当然,会有一些准确使用也有的奇怪问题)

当然,如果Header和Footer也使用estimated的话,就在willDisplayHeaderView 和 willDisplayFooterView 把实际高度也存储起来就行了。不需要的话就把estimated设置为0。

你可能感兴趣的:(较为优雅地解决UITableView在reloadData时跳动的问题)