当创建一个UITableView并且每当你发送一个reloadData消息时,数据源就会为每个单元发送一个heightForRowAtIndexPath消息。所以如果你的表格有30个单元格,那么这个消息会被发送30次。
说这30个单元格中只有6个在屏幕上可见。在这种情况下,当创建并发送reloadData消息时,UITableView将在每个可见行发送一个cellForRowAtIndexPath消息,即该消息被发送六次。
苹果为什么像这样实施它?其中一部分原因是,计算行高度比构建和填充整个单元格要便宜得多。鉴于在许多表格中,每个单元格的高度都是相同的,它通常要便宜得多。部分原因是因为iOS需要知道整个表的大小:这允许它创建滚动条并将其设置在滚动视图中等。
如果您的行高因尺寸不同而不同可以使用不同数量的文本,您可以使用相关字符串上的sizeWithFont:方法之一来进行计算。这比构建视图然后测量结果更快。请注意,如果您更改单元格的高度,则需要重新加载整个表格(使用reloadData - 这将询问代表每个高度,但只询问可见单元格),或者选择性地重新加载大小已满的行改变。
其他材料 如果我理解在评论跟进的问题,以下可能会有帮助:
如果要实现编辑模式,那么它的情况并不少见需要改变你的表的高度行。例如,您的表格行中可能有文本,并且它们的单元格变得更窄时 - 为右侧的删除圆圈留出空间 - 您可能希望某些单元格变得更高以容纳文本。这里的基本方法是:
确保tableView:heightForRowAtIndexPath:方法知道您是否处于编辑模式。 (它可以使用isEditing来询问tableView。)然后让方法返回正确的高度,这取决于你是否处于编辑模式。
在UITableViewController中的setEditing:animated方法(或者UIViewController,无论你使用什么 - 取决于你使用什么,都有一些差异,所以值得仔细检查文档)发送reloadData消息到tableView之后你已经改变了它的状态。这将强制tableView抓住每一行的高度,并将重新获取可见行的单元格。当您进入编辑模式时,tableView处理使单元变窄,但如果您想在布局上做更多工作,请在tableView:cellForRowAtIndex:中执行。如上所述,总体策略是找到一种快速计算高度的方法。随着文字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;
我已经在我的自定义的UITableViewCell子引入一个类的方法做到了这一点,正如你所提到的。它有效,但我也质疑效率。 – chris 2011-03-14 06:15:09