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

Tom*_*m G 6 objective-c uitableview ios autolayout

目前的设置:

TableView具有自动计算的高度:

self.tableView.sectionHeaderHeight = UITableViewAutomaticDimension;
self.tableView.rowHeight = UITableViewAutomaticDimension;
self.tableView.estimatedRowHeight = 152.0;
self.tableView.estimatedSectionHeaderHeight = 50.0;
Run Code Online (Sandbox Code Playgroud)

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

 - (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
    [self.tableView reloadData]; 
}
Run Code Online (Sandbox Code Playgroud)

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

问题:

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

附加信息

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

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

在此输入图像描述

bte*_*pot 8

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

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

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