创建 UITableView 并且无论何时向它发送 reloadData 消息时,都会为每个单元格向数据源发送一个 heightForRowAtIndexPath 消息。因此,如果您的表格有 30 个单元格,则该消息将被发送 30 次。
假设这 30 个单元格中只有 6 个在屏幕上可见。在这种情况下,当您创建它并发送一个 reloadData 消息时,UITableView 将为每个可见行发送一个 cellForRowAtIndexPath 消息,即该消息被发送六次。
苹果为什么要这样实现?部分原因是计算行高几乎总是比构建和填充整个单元格便宜。并且鉴于在许多表格中每个单元格的高度都是相同的,因此通常要便宜得多。部分原因是因为 iOS 需要知道整个表格的大小:这允许它创建滚动条并将其设置在滚动视图等上。
如果您的行高因包含不同数量的文本而大小不同,则可以对相关字符串使用 sizeWithFont: 方法之一来进行计算。这比构建视图然后测量结果要快。请注意,如果您更改单元格的高度,您将需要重新加载整个表格(使用 reloadData - 这将询问代表每个高度,但只询问可见单元格)或有选择地重新加载大小有的行改变了。
附加材料
如果我理解评论中的后续问题,以下内容可能会有所帮助:
如果您正在实施编辑模式,那么需要更改表格行的高度并不少见。例如,您的表格行中可能有文本,当它们的单元格变窄时 - 为右侧的删除圆圈腾出空间 - 您可能希望某些单元格变高以容纳文本。这里的基本方法是:
确保 tableView:heightForRowAtIndexPath: 方法知道您是否处于编辑模式。(它可以使用 isEditing 询问 tableView。)然后获取返回正确高度的方法,具体取决于您是否处于编辑模式。
在 UITableViewController 中的 setEditing:animated: 方法(或 UIViewController,无论您使用的是哪一个 - 根据您使用的内容存在一些差异,因此值得仔细检查文档)在您更改其状态后向 tableView 发送 reloadData 消息. 这将强制 tableView 获取每一行的高度,并将重新获取可见行的单元格。当您进入编辑模式时,tableView 会处理使单元格变窄的问题,但是如果您想在布局上做更多的工作,请在 tableView:cellForRowAtIndex: 中进行。如上所述,一般策略是找到一种快速计算高度的方法。使用 text sizeWithFont: (及其变体) 可以做到。如果您有图像等,那么您可以获取它们的尺寸并进行一些总和。
除了这些步骤之外,您可能还希望在切换模式后稍微滚动一下 tableView。如果您的行的高度不同,那么您将在切换模式后最终在表格中的错误位置。我在这里采取的一种方法是在我重新加载表格后使用 performSelector:withObject:afterDelay 来调用一个进行滚动调整的方法。您需要使用延迟,让 tableView 有时间收集新的高度和新的表格单元格。(可能有更聪明的方法。)我做了一些总和,根据 tableView:cellForRowAtIndexPath: 的 origin.y 之间的差异进行滚动调整:在重新加载之前和之后屏幕上的单元格第一个可见行。因此,例如,要在预加载之前获得位置,有点像这样。
CGPoint offset = [[self tableView] contentOffset];
NSIndexPath* indexPath = [[self tableView] indexPathForRowAtPoint:CGPointMake(0,offset.y)];
CGFloat preCellOffset = [[[self tableView] cellForRowAtIndexPath:indexPath] origin].y;