美文网首页
UITableView滚动流畅性的优化

UITableView滚动流畅性的优化

作者: LeoCao | 来源:发表于2016-10-28 23:02 被阅读0次

影响UITableView滚动的流畅性优化的原因

1、在代理方法中做了过多的计算占用了UI线程的时间

2、cell中view的组织复杂;eg:使用layer并不会有太大影响,但是layer层如果使用了透明、圆角、变形等效果,就会影响到绘制速度;

在代理方法中做了过多的计算占用了UI线程的时间

关于第一点首先要明白 tableView的代理的调用顺序

1、通过代理设置行数 number of rows

2、通过代理没行设置行高度 heightForRoeAtIndexPath

3、通过代理设置当前屏幕可见的元素 cellForRowAtIndexPath(实测显示4寸屏的手机会取屏幕显示数量+2,3.5寸屏幕同4寸数量,虽然3.5寸屏幕可显示的cell的数量要小于4寸)

4、绘制cell 

关于第一点,首先要明白tableView的代理(这里是指datasource 和 delegate 的那套代理方法,下同方法的调用顺序和时机。对于一般的应用会有如下的顺序呢:

1、向代理要  number of rows.

2、对于每行向代理要 heoght For Row At IndexPath

3、向当前屏幕要可见的cell For Row At IndexPath(实测显示4寸屏的手机会取屏幕显示数量 +2, 3.5 寸屏幕同4 寸屏幕数量,虽然 3.5 寸可显示的 cell 数量要小于 4 寸屏)

4、然后 cell 就显示出来了

tableView:heig htForRowAtIndexPath:

很多人把优化重点放到了 cell for row at indexPath 那个代理方法里了,在这里尽可能的少计算,但是却忽略了另一个很轻松就能提升加载速度的方法:

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath

tableView在每次 reload data 时都会要所有cell的高度!这就是说你有100 行 cell 。走100 次这个代理方法来设置cell 的高度,而不是当前屏幕显示的cell 的数量的高度,虽然在 iOS7下多了计算 cell 的高度的 方法,但是减少计算高度时的时间,对于提升加载tableView的速度有非常明显的提高

-(CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath(iOS7专用)

但是有人说了“我早听人说了,reloadData方法尽量不要调用,我插入新行都用insertRowAtIndexPaths:WithROwAnimation: 删除也用delegate那个,这个中性了吧?”;这样也不能忽略heightForRowAtIndexPath 这个回调的重要性,因为在每次删除或者插入一行后同样也要调用以便返回所有行的这个回调方法!是所有行!你没有看错,所有所以只需减少一个代理方法的计算量,就可以明显的提升加载速度。

对于减少tableView:heihghtForRowAtIndexPath:计算量,就尽量让这个方法的计算计算复杂度为O(1);就是只是简单的从数组中取出一个值,然后返回!

也许有人要问了,我们的应用都是动态的高度,就像微博那样的,不定数量的文字,还有图片,大小也不固定,这些怎么返回固定的高度啊?

我指的固定高度并不是row的高度都一定那种固定,而是让在tableView:heightForRowAtIndexPath:这个回调里取这个高度的时间是近乎固定的

对于高度的计算,还有个小细节需要注意,就是入如果row 的高度都一定,那么就删除tableView:heightForRowAtIndexPath:这个方法,设置tableView的rowHeight属性,相似的numberOfRowsInSection:系列的方法,我就不写出来了,苹果文档里写这样做可以减少调用时间。

现在回归正题,对于cell的高度不固定,传统的方法是为cell写个计算行高的类方法,传入那些动态的元素(文字、图片等)然后返回计算的高度。在tableView:hieghtForRoeAtIndexPath:中调用这个方法,填入需要的参数计算cell高度。这当然没有什么问题,只是要是计算量很复杂,你每次reoadData,光计算行高就花去rowCount *单行高评价计算时间 ,想想有100行,你不定期的要reloadData 或者 insert(delete)row ...... 结局办法就是:

   用空间换时间

将计算行高的时间提前到从服务器请求会数据的时候,计算完了高度一并写回数据库 ,别告诉我你在你在主线程里阻塞式的处理网络请求。。。。。。面壁思过去吧,别浪费了 GCD,NSOPerationQueue的青春。最先想到的还是NSThread同学,证明你已经老了。。。现在几乎大部分的多线程操作都不需要NSThread和Runloop了

tableView:cellForRowAtIndexPath:

说完了计算cell的行高的优化,现在来谈 tableView:cellForRowAtIndexPath: 回调的优化。优化思路同上,也是通过预处理来减少这个回调中的计算时间。这个回调重点谈的是对图片异步加载的优化

图片异步加载无非就是在这个方法里发起异步请求,图片加载完成后根据 UIImageView 的引用设置时间。有经验的程序员可能会使用懒加载的方式减少快速滑动时由于网络请求过于频繁与切换线程显示图片造成的卡顿。这里还有个问题,拿回来的图片一定和最后显示的大小不一样,有时候偷懒,直接设置imageView 的contentMode 属性为 imageView自己”压缩“,这是一个很取巧的方法,但是 tableView 的滚动速度也会造成不容忽视的影响。对图片变形需要对图片做 transForm,每次变换图片都要对图片乘以一个变幻矩阵,如果你的图片很多,计算量是不可忽视的。

        优化建议:从网络请求回来的图片先根据需要显示的图片大小切成合适大小的图,每次只显示处理过的大小的图片,当查看大图时再显示大图。如果服务器能但会处理好的大图和图片的大小更好。

使用Instrument 的 Core Animation 模板可以查看图片的压缩情况。

        Instrument 中的 Core Animation 模板只有在调试真机时才有,调适模拟器上的应用没有这个模板!!!但是可以再模拟器的Debug菜单下找到这些调适选项、

切记:调适应用性能一定要用真机,Mac 的性能完爆 iPhone,所以不要说我的应用在模拟机上调适不卡啊! 模拟器只是模拟iOS 软件的运行环境,不能模拟硬件性能!

Color Misaligned Images 这些选项对设备的所有应用有效,也就是你不需要选择 target 就能调适它(方便竞品分析:)

对于 MisAligned Images 会有两种颜色:一种是洋红色,一种是黄色、

Misaligned Images 洋红色是因为像素没对齐,比如上面的label。一般情况下是因为像素没对齐。需要抵抗锯齿,像素会出现模糊的现象。

        解决办法:在设置 view 的 frame 的时候,在高分屏避免出现21.3,6.7这样的小数,尤其是x,y坐标,用ceil 或 floor 或 round 取整。每 0.5 个点对应一个 pixel,o.3,0.7这样就难为iPhone 了。低分屏不要出现小数

黄色是因为显示的图片实际大小与显示大小不同,对图片进行了拉伸,测试显示使用 imageView 显示实际大小的图也会变黄。

     减少洋红色和黄色可以提升滚动的流畅性

手动 Drawing 试图提升流畅性

如果通过上面的方法,滚动速度还不能达到可以容忍的速度,那就只剩下最后y一个方法了:手动绘制视图

手动绘制方法,不是直接子类化UITableViewCell ,然后覆盖drawRect:方法,这样你会得到一个大黑块! 因为cell 中不是只有一个 contentView。 如果不了解 cell 的层次结构,可以去 Reveal 去看下。

绘制cell 不建议使用 UIView ,建议使用 CALayer, UIView 的绘制是建立在 CoreGraphic上的,使用的是CPU。 CALAyer 使用的是 Core Animation,CPU,GPU通吃,有系统决定使用哪个。 View 的绘制是自下向上的一层一层的绘制,然后渲染; layer 处理的是 Texure, 利用 GPU 的 Texture cache 和独立的浮点数计算单元加速纹理的处理

问题已解: 在UIView 的 drawRect 里使用 CG开头的绘图命令只是触发的伪离屏渲染,绘图还是靠 CPU 同步的在主线程绘制,在 layer 中触发的 离屏渲染会触发真正的离屏渲染,在一个独立的进程里绘制。

https://lobste.rs/s/ckm4uw/a_performance-minded_take_on_ios_design/comments/itdkfh

GPU 不喜欢透明,所以所有的图一定要弄成不透明,

相关文章

网友评论

      本文标题:UITableView滚动流畅性的优化

      本文链接:https://www.haomeiwen.com/subject/pvveuttx.html