这个方法对于cell定高的UITableView来说没有意义,但如果由于某些原因需要动态高度的cell的话,这个方法可以很容易地让滑动更流畅。
正如我们所知,UITableView是UIScrollView的子类,而UIScrollView的作用是让用户可以与比屏幕实际尺寸更大的区域交互。任何UIScrollView的实例都使用诸如contentSize、contentOffset和其它许多属性来将正确的区域显示给用户。
但是UITableView的问题在哪?正如所解释的一样,UITableView不会同时维护所有cell的实例。相反,它只需要维护显示给用户的那些cell。
那么,UITableView是如何知道它的contentSize呢?它是通过计算所有cell的高度之和来计算contentSize的值。
UITableView的delegate方法tableView:heightForRowAtIndexPath:会为每个cell调用一次,所以你应该非常快地返回高度值。
很多人会犯一个错误,他们会在布局初始化cell实例并绑定数据后去获取它们的高度。如果你想优化滑动的性能,就不应该以这种方式来计算cell的高度,因为这事难以置信的低效,iOS设备标准的60 FPS将会降低到15-20 FPS,滑动会变得很慢。
从iOS 8开始,我们可以在UITableView的delegate中使用自动高度计算,而不需要实现上面提到的方法。为了实现这一功能,你可能会使用AutoLayout,并将rowHeight变量设置为UITableViewAutomaticDimension。可以在StackOverflow中找到更多详细的信息。
尽管可以使用这些方法,但我强烈建议不要使用它们。另外,我也不建议使用复杂的数学计算来获取cell的高度,如果可能,只使用加、减、乘、除就可以。
但如果是AutoLayout呢?它真的跟我所说的一样慢么?你可能会很惊讶,但这是事实。如果你想让你的App在所有设备上都能平滑的滚动,你就会发现这种方法难以置信的慢。你使用的子视图越多,AutoLayout的效率越低。
使用内建方法优化UITableView的正确方法是:
重用cell实例:对于特殊类型的cell,你应该只有一个实例,而没有更多。
不要在cellForRowAtIndexPath:方法中绑定数据,因为在此时cell还没有显示。可以使用UITableView的delegate中的tableView:willDisplayCell:forRowAtIndexPath:方法。
快速计算cell高度。对于工程师来说这是常规工作,但你将会为优化复杂cell的平滑滑动所付出的耐心而获取回报。
我们需要更深一步
当然,上面提到的这些点不足以实现真正的平滑滚动,特别是当你需要实现一些复杂的cell(如有大量的渐变、视图、交互元素、一些修饰元素等等)时,这变得尤其明显。
这种情况下,UITableView很容易变得缓慢,即便是做了上面所有的事情。UITableViewCell中的视图越多,滑动时FPS越低。但在使用了手动布局和优化了高度计算后,问题就不在布局了,而在渲染了。
让我们把关注点放在UIView的opaque属性上。文档中说它用于辅助绘图系统定义UIView是否透明。如果不透明,则绘图系统在渲染视图时可以做一些优化,以提高性能。
我们需要性能,或者不是?用户可能快速地滑动table,如使用scrollsToTop特性,但他们可能没有最新的iPhone,所以cell必须快速地被渲染。比通常的视图更快。
渲染最慢的操作之一是混合(blending)。混合操作由GPU来执行,因为这个硬件就是用来做混合操作的(当然不只是混合)。