当前设置:
具有自动计算高度的 TableView:
TableView with automatically calculated heights:
self.tableView.sectionHeaderHeight = UITableViewAutomaticDimension;
self.tableView.rowHeight = UITableViewAutomaticDimension;
self.tableView.estimatedRowHeight = 152.0;
self.tableView.estimatedSectionHeaderHeight = 50.0;
每当获取的结果控制器更新其数据时,表格视图就会重新加载:
Whenever the fetched results controller updates its data the tableview is reloaded:
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
[self.tableView reloadData];
}
使用 Xib 配置单元.第一个标签固定在单元格的顶部,后面的每个标签都固定在其上方标签的顶部,底部的标签固定在单元格的底部.
The cell is configured using a Xib. The first label is pinned to the top of the cell, each following label is pinned to the top of the label above it and the label at the bottom is pinned to the bottom of the cell.
问题:
每次我设置一个收藏夹"时表视图中项目的属性,获取的结果控制器被触发以重新加载表并更改滚动位置.我正在尝试修复的正是滚动位置的这种变化.
Each time i set a "Favourite" property on an item in the table view, the fetched results controller is fired to reload the table and the scroll position is changed. It is this change in the scroll position that i am trying to fix.
其他信息
如果我使用固定的单元格高度,它可以解决问题,但我需要 UITableViewAutomaticDimension,因为第一个标签可以跨越两行,其余标签可能存在也可能不存在.
If i use fixed cell heights it resolves the issue BUT i require UITableViewAutomaticDimension because the first label can wrap over two lines and the remaining labels may or may not be present.
示例
注意 - 当我选择 Fav 按钮时,它会在 Core data 中设置 fav 属性并重新加载表格.为什么桌子会跳来跳去?
Note - As i select the Fav button it sets the fav property in Core data and reloads the table. Why is the table jumping around?
它的发生是因为以下顺序:
It happens because of the following sequence:
-tableView:heightForRowAtIndexPath:
方法在显示每个单元格之前询问其委托的确切高度.contentOffset.y
现在是 220.contentOffset.y
是 220.UITableView 现在开始填充其内容.首先,它需要知道其内容的大小以正确调整其滚动指示器的大小和位置.它还需要知道哪些对象 - 表头、节头、行、节脚和表脚 - 它应该根据其当前的 bounds
显示,哪个位置也由 contentOffset表示代码>.要开始放置可见对象,首先需要跳过不可见垂直范围 [0…220] 内的对象.
-tableView:heightForRowAtIndexPath:
.contentOffset.y
is now 220.contentOffset.y
which is 220.UITableView now beginning to fill its contents. First it needs to know size of its contents to correctly size and position its scroll indicators. It also needs to know which objects - table header, section headers, rows, section footers and table footer - it should display according to its current bounds
, which position is also represented by contentOffset
. To begin placing that visible objects it first needs to skip objects that falls in invisible vertical range of [0…220].
estimated…
属性提供值并且没有实现任何 tableViewController:estimated…
方法,那么 UITableView 会询问其委托人确切的高度通过调用适当的委托方法(例如 -tableView:heightForRowAtIndexPath:
)来控制页眉、页脚和行.如果您的代理报告的对象数量和它们的高度与重新加载之前相同,那么您将不会看到任何表格元素的位置和大小的任何视觉变化.当您的表格应该显示大量行时,这种海峡"行为的不利因素变得明显,比如说 50000.UITableView 向其委托询问这 50000 行中每一行的高度,您必须通过测量每个对应的文本来自己计算它对象,或者当使用 UITableViewAutomaticDimension
UITableView 进行相同的测量时,向其代表询问填充了文本的单元格.相信我,它很慢.每次重新加载都会导致界面冻结几秒钟.estimatedRowHeight
或 -tableView:estimatedHeightForRowAtIndexPath:
中提供的值来计算行,并通过相应的方法用于节页眉和页脚.通过将 estimatedRowHeight
设置为 60,您可以告诉 UITableView 跳过三行 (60 * 3 = 180) 并将第 4 行与顶部可见边缘的偏移量设置为 -40.因此视觉上跳跃"了 40 个像素.estimated…
properties and haven't implemented any of tableViewController:estimated…
methods then UITableView asks its delegate about exact height of headers, footers and rows by calling appropriate delegate methods such as -tableView:heightForRowAtIndexPath:
. And if your delegate reports the same number of objects and the same heights for them as before reload, then you will not see any visual changes to position and size of any table elements. Downside of this "strait" behavior became obvious when your table should display large number of rows, lets say 50000. UITableView asks its delegate about height of each of this 50000 rows, and you have to calculate it yourself by measuring your text for each corresponding object, or when using UITableViewAutomaticDimension
UITableView doing the same measuring itself, asking its delegate for cells filled with text. Believe me, it's slow. Each reload will cause a few seconds of interface freeze.estimatedRowHeight
or -tableView:estimatedHeightForRowAtIndexPath:
for rows and by corresponding methods for section headers and footers. By setting estimatedRowHeight
to 60, you telling UITableView to skip three rows (60 * 3 = 180) and to place row 4 with offset of -40 from top visible edge. Hence visual "jump" by 40 pixels up.这里的正确"解决方案是不调用 reloadData
.只为更改的对象重新加载行,使用 -reloadRowsAtIndexPaths:withRowAnimation:
.如果 NSFetchedResultsController + UITableView 使用这个 经典方案.
A "right" solution here would be not to call reloadData
. Reload rows only for changed objects instead, use -reloadRowsAtIndexPaths:withRowAnimation:
. In case of NSFetchedResultsController + UITableView use this classic scheme.
这篇关于UITableView 由 FetchedResultsController 和 UITableViewAutomaticDimension 提供支持 - 重新加载表格时单元格移动的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!