UITableView由带有UITableViewAutomaticDimension的FetchedResultsController提供 – 当表重新加载时单元格移动

目前的设置:

TableView具有自动计算的高度:

self.tableView.sectionHeaderHeight = UITableViewAutomaticDimension; self.tableView.rowHeight = UITableViewAutomaticDimension; self.tableView.estimatedRowHeight = 152.0; self.tableView.estimatedSectionHeaderHeight = 50.0; 

只要获取的结果控制器更新其数据,就会重新加载tableview:

  - (void)controllerDidChangeContent:(NSFetchedResultsController *)controller { [self.tableView reloadData]; } 

使用Xib配置单元。 第一个标签固定在单元格的顶部,每个标签固定在其上方标签的顶部,底部的标签固定在单元格的底部。

问题:

每次我在表视图中的项目上设置“collections夹”属性时,将触发获取的结果控制器以重新加载表并更改滚动位置。 这是我想要修复的滚动位置的这种变化。

附加信息

如果我使用固定的单元格高度它解决了问题但我需要UITableViewAutomaticDimension,因为第一个标签可以包裹两条线,其余标签可能存在也可能不存在。

注意 – 当我选择Fav按钮时,它在Core数据中设置fav属性并重新加载表。 桌子为什么跳来跳去?

在此处输入图像描述

它发生的原因是以下顺序:

  1. UITableView初始化并显示5个单元格。 UITableView知道每个单元格的高度。 它通过调用方法-tableView:heightForRowAtIndexPath:在显示每个单元格之前询问其委托者的确切高度。
  2. UITableView从顶部精确滚动了3个单元格。 已知该细胞的高度正好是[60,70,90] = 220。 UITableView的contentOffset.y现在是220。
  3. UITableView被重新加载。 它清除了所有关于细胞的知识。 它现在仍然知道它的contentOffset.y是220。
  4. UITableView询问有关一般指标的数据源 – 每个部分的部分数和行数。
  5. UITableView现在开始填充其内容。 首先,它需要知道其内容的大小,以正确地调整其滚动指示器的大小和位置。 它还需要知道哪些对象 – 表头,节头,行,节页脚和表尾 – 它应该根据其当前bounds显示,哪个位置也由contentOffset表示。 要开始放置那些可见对象,首先需要跳过落在[0 … 220]的不可见垂直范围内的对象。

    1. 如果你没有为任何estimated…属性提供值,并且没有实现任何tableViewController:estimated…方法,那么UITableView通过调用适当的委托方法(如-tableView:heightForRowAtIndexPath:询问其委托关于页眉,页脚和行的确切高度-tableView:heightForRowAtIndexPath: 。 如果您的委托报告与重新加载之前相同数量的对象和相同的高度,那么您将看不到任何表元素的位置和大小的任何可视更改。 当你的表显示大量行时,这个“海峡”行为的下行变得明显,比方说50000.UITableView向其代表询问这50000行中每一行的高度,你必须自己通过测量每个对应的文本来计算它。对象,或者当使用UITableViewAutomaticDimension UITableView做同样的测量本身时,向其委托询问填充文本的单元格。 相信我,它很慢。 每次重新加载都会导致几秒钟的界面冻结。
    2. 如果您提供了具有估计高度的UITableView,那么它将仅询问其代理当前可见对象的高度。 垂直范围为[0 … 220]的对象通过使用estimatedRowHeight-tableView:estimatedHeightForRowAtIndexPath:提供的值进行计数,用于行以及用于节头和页脚的相应方法。 通过将estimatedRowHeight设置为60,您可以告诉UITableView跳过三行(60 * 3 = 180)并将第4行与顶部可见边缘的偏移量设置为-40。 因此视觉“跳跃”40像素。

这里的“正确”解决方案不是调用reloadData 。 仅为已更改的对象重新加载行,使用-reloadRowsAtIndexPaths:withRowAnimation: . 在NSFetchedResultsController + UITableView的情况下使用这个经典方案 。