为啥 UITableView contentOffset 在 tableview reloadData 期间变化很大,而不是保持不变? reloadData 后如何使其保持不变?

Posted

技术标签:

【中文标题】为啥 UITableView contentOffset 在 tableview reloadData 期间变化很大,而不是保持不变? reloadData 后如何使其保持不变?【英文标题】:Why UITableView contentOffset varies wildly during tableview reloadData instead of just stay the same? How to make it stay the same after reloadData?为什么 UITableView contentOffset 在 tableview reloadData 期间变化很大,而不是保持不变? reloadData 后如何使其保持不变? 【发布时间】:2018-08-06 03:47:00 【问题描述】:

我正在浏览互联网但没有令人满意的结果。我有一个tableView,每当我做reloadData 时,它的偏移量总是不规律地变化。即使表格的内容保持不变,也会发生这种情况。

我使用scrollViewDidScroll 记录了在运行reloadData 时偏移量如何变化。

func scrollViewDidScroll(_ scrollView: UIScrollView) 
    print ("TABLEVIEW OFFSET : \(scrollView.contentOffset)");

我还创建了一个代码来保存 reloadData 之前的旧偏移量,并在延迟后重新设置为新的偏移量。

extension UITableView 

    func reloadDataOffset() 
        print ("OLD OFFSET : \(self.contentOffset)");
        let offset = self.contentOffset;
        let oldHidden = self.isHidden;
        self.isHidden = true;
        self.reloadData();
        delay(1) 
            self.setContentOffset(offset, animated: false);
            self.isHidden = oldHidden;
            print ("NEW OFFSET : \(self.contentOffset)");
        
    


这是日志中显示的内容。

OLD OFFSET : (0.0, 314.0)
TABLEVIEW OFFSET : (0.0, -64.0)
TABLEVIEW OFFSET : (0.0, 314.0)
TABLEVIEW OFFSET : (0.0, -64.0)
TABLEVIEW OFFSET : (0.0, 753.0)
TABLEVIEW OFFSET : (0.0, 586.0)
TABLEVIEW OFFSET : (0.0, 753.0)
TABLEVIEW OFFSET : (0.0, 706.0)
TABLEVIEW OFFSET : (0.0, 753.0)
TABLEVIEW OFFSET : (0.0, 751.5)
TABLEVIEW OFFSET : (0.0, 750.0)
TABLEVIEW OFFSET : (0.0, 747.5)
TABLEVIEW OFFSET : (0.0, 744.5)
TABLEVIEW OFFSET : (0.0, 741.0)
TABLEVIEW OFFSET : (0.0, 737.5)
TABLEVIEW OFFSET : (0.0, 733.5)
TABLEVIEW OFFSET : (0.0, 729.5)
TABLEVIEW OFFSET : (0.0, 725.5)
TABLEVIEW OFFSET : (0.0, 721.5)
TABLEVIEW OFFSET : (0.0, 717.5)
TABLEVIEW OFFSET : (0.0, 714.5)
TABLEVIEW OFFSET : (0.0, 711.5)
TABLEVIEW OFFSET : (0.0, 709.0)
TABLEVIEW OFFSET : (0.0, 707.5)
TABLEVIEW OFFSET : (0.0, 706.5)
TABLEVIEW OFFSET : (0.0, 706.0)
TABLEVIEW OFFSET : (0.0, 314.0)
NEW OFFSET : (0.0, 314.0)

我这样做(添加延迟)是因为我在某处读到 tableView reloadData 发生在不同的线程中,并且每当 reloadData 完成时我无法准确地获得回调或通知。但这看起来很丑陋。我可以删除isHidden = true 部分,但这会使表格内容看起来跳来跳去。有什么真正的方法可以在 reloadData 完成后立即将偏移量重新设置为旧值?或者,有什么方法可以让滚动偏移在 reloadData 之前/之后保持原位?

【问题讨论】:

@matt 即使我把所有的print 都去掉了,结果还是一样,到处乱跳。 对于那些因为不清楚而投票结束我的问题的人,我认为我已经在问题标题中尽可能清楚地说明了问题。请告诉我哪一部分不清楚,让我解决。 【参考方案1】:

我在viewDidLoad() 中调用后终于修复它:

tableView.estimatedRowHeight = 0;
tableView.estimatedSectionHeaderHeight = 0;
tableView.estimatedSectionFooterHeight = 0;

看起来这是 ios 11 的一个新的默认“模糊功能”,在我的情况下,它造成的损害大于帮助。这就是为什么我在 iOS 11 之前从未遇到过这个问题。这估计会弄乱我的表格内容大小和内容偏移控制。尝试关闭这三个估计,您会看到UITableView 不稳定的contentOffsetcontentSize 将再次在您的控制之下运行。我真的希望 Apple 在添加时将此类功能默认为禁用,以免与没有为新更改做好准备的旧代码混淆。

【讨论】:

我怀疑您的 tableview 不知道您的单元格的确切高度。 @CynichniyBandera 我忘了在上面提到我也已经实现了“heightForRow”功能。但是在计算 contentSizecontentOffset 时,tableView 似乎没有将其用作参考 reloadData

以上是关于为啥 UITableView contentOffset 在 tableview reloadData 期间变化很大,而不是保持不变? reloadData 后如何使其保持不变?的主要内容,如果未能解决你的问题,请参考以下文章

为啥UITableView不能reloadData

为啥第一次滚动到另一个 UITableView 中的 UICollectionView 中的 UITableView 不加载数据?

我在学习iOS的UITableView,为啥UITableView的最后一块单元格只能显示一半? [关闭]

为啥我的 UITableView 不显示数据?

为啥 UITableViewCell 宽度小于 UITableView 宽度

为啥滚动 UITableView 比滚动 UIScrollView 响应更快?