影响 UITableView 滚动的流畅性的原因
1、 在代理方法中做了过多的计算占用了 UI 线程的时间
2、同上
3、Cell 中 view 的组织复杂
关于第一点,首先要明白 tableview 的代理(这里指 datasource 和 delegate 的那套方法,下同)方法的调用顺序,和时机。对于一般的应用会有如下顺序:
1、向代理要 number Of Rows。
2、对于每行向代理要 height For Row At Index Path。
3、向代理要 当前屏幕可见的 cell For Row At Index Path 。(实测显示4寸屏的手机会取 屏幕显示数量+2,3.5寸屏同4寸屏数量,虽然3.5寸屏可显示的cell 数量要小于 4寸屏!)
4、然后 cell 就显示出来了。
tableView:heightForRowAtIndexPath:
很多人都把优化的重点放到了 cell for row at indexpath 那个方法里了,在这里尽可能的少计算,但是却忽略了另一个很轻松就能提升加载时间的方法 :
  1. - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
Table View 在每次 reload data 时都会要所有 cell 的高度!这就是说你有一百行 cell,就像代理要100次每个cell 的高度,而不是当前屏幕显示的cell 的数量的高度!虽然在 iOS 7 下多了计算 cell 高度的方法,但是减少 计算高度时的时间,对于提升加载 Table View 的速度有非常明显的提高!
  1. - (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath
  2. (**iOS 7专用**)
但是有人说了,我早听别人说了,reloadData 方法尽量不要调用,我插入新行都用 insertRowsAtIndexPaths:withRowAnimation: 删除也用 delete 那个,这个总行了吧?!
这样也不能忽略 height For Row At Index Path 这个回调的重要性。因为在每次插入或者删除一行后同样需要调用一遍 所有行 的这个回调方法!是所有行!你没看错,所有只是简单的减少一个代理方法的计算量,就可以明显的提升加载速度。
对于提升 tableView:heightForRowAtIndexPath: 计算量,就是尽可能的让这个方法的计算复杂度为 O(1),就是只是简单的从数组中取一个值,然后返回!
也许有人又要问了,我的应用都是动态的高度,就像微博那样的,不定数量的文字,可能还有图片,大小也不固定,这些怎么返回固定的高度啊?
我指的固定高度不是 row 的高度都一样那种固定,而是让在 tableView:heightForRowAtIndexPath: 这个回调里取这个高度的时间是近乎固定的。
对于高度的计算,还有个小细节需要注意,就是如果 row 的高度都一定,那就删除代理中的这个 tableView:heightForRowAtIndexPath: 方法,设置 Table View 的 rowHeight 属性,相似的 numberOfRowsInSection: 系列的方法,我就不都写出来了。苹果的文档里介绍这样也可以减少了调用时间。
现在回归正题。对于 cell 高度不固定的,传统的方法是为 cell 写个计算行高的类方法,传入那些动态的元素(文字,图片等),然后返回计算后的高度。在 tableView:heightForRowAtIndexPath: 中调用这个方法,填入需要的参数计算cell 高度。这当然没有什么问题,只是要是计算量很复杂,你每次 reloadData ,光计算行高就要花去 rowCount * 单行高评价计算时间,想想有100行,你不定期的需要 reloadData 或者 insert(delete) row......解决办法就是:
用 “空间换时间”
将计算行高的时间提前到从服务器搂回数据的时候,计算完了高度一并写回数据库,别告诉我你在主线程里阻塞式的处理网络请求。。。。面壁思过去吧,别浪费了 GCD,NSOperationQueue的青春。最先想到的还是 NSThread 的同学,证明你已经老了。。。现在几乎大部分的多线程操作都不需要用到 NSThread 和 runloop了。
tableView:cellForRowAtIndexPath:
说完了计算 cell 行高的优化,现在来谈 tableView:cellForRowAtIndexPath: 回调的优化。优化思路同上,也是通过预处理减少在这个回调中的计算时间。这个回调重点谈的是对图片异步加载的优化。
图片异步加载无非就是在这个方法里发起异步请求,图片加载完后根据 UIImageView 的引用设置图片。有经验的程序员可能会使用 懒加载 的方式减少快速滑动时因为网络请求过于频繁与切换线程显示图片造成的卡顿。这里还有个问题,拿回来的图片一定和最后显示的大小不一样,有时候偷懒,直接设置 image view 的 contentMode 属性要 image view 自己 压缩。这是一个很取巧的方法,但是对 table view 的滚动速度也会造成 不容忽视 的影响。对图片变形需要对图片做 transform ,每次压缩图片都要对图片乘以一个变换矩阵,如果你的图片很多,这个计算量是不同忽视的。
优化建议:从网络搂回来图片后先根据需要显示的图片大小切成合适大小的图,每次只显示处理过大小的图片,当查看大图时在显示大图。如果服务器能直接返回预处理好的小图和图片的大小更好。
使用 Instrument 的 Core Animation 模板可以查看图片的压缩情况。如图:
Instrument 中的 Core Animation 模板只有在调试真机时才有,调试模拟器上的应用没有这个模板!!!但是可以在模拟器的 Debug 菜单下找到这些调试选项。
 
切记:调试应用性能一定要用真机,Mac 的性能完爆 iPhone,所有不要说我的应用在模拟器上调试时不卡啊!模拟器只能模拟 iOS 软件的运行环境,不能模拟硬件性能!
这些选项对设备的所有应用有效,也就是说你不需要选择 target 就能调试 它(方便竞品分析 :)!
对于 Misaligned images 会有两种颜色:一种是洋红色,另一种是黄色。
洋红色是因为像素没对齐,比如上面的 label,一般情况下因为像素没对齐,需要抗锯齿,图像会出现模糊的现象。
解决办法:在设置 view 的 frame 时,在高分屏避免出现 21.3,6.7这样的小数,尤其是 x,y坐标,用 ceil 或 floor 或 round 取整。每 0.5 个点对应一个 pixel,0.3,0.7这样的就难为 iPhone 了,低分屏不要出现小数。
 
黄色是因为显示的图片实际大小与显示大小不同,对图片进行了拉伸,测试显示使用 image view 显示实际大小的图也会变黄。
减少洋红色和黄色可以提升滚动的流畅性
手动 Drawing 视图提升流畅性
如果通过上面的方法,滚动速度还不能达到可以容忍的速度,那就只剩下最后一个办法了,手动绘制视图。
手动绘制方法,不是直接子类化 UITableViewCell,然后覆盖 drawRect: 方法,这样你会得到一个大黑块!因为 cell 中不是只有一个 content view。如果不了解 cell 的层次结构,可以用 Reveal 去看下。
绘制 cell 不建议使用 UIView,建议使用 CALayer。 UIView 的绘制是建立在 CoreGraphic 上的,使用的是 CPU。CALayer 使用的是 Core Animation,CPU,GPU 通吃,由系统决定使用哪个。View的绘制使用的是自下向上的一层一层的绘制,然后渲染。Layer处理的是 Texure,利用 GPU 的 Texture Cache 和独立的浮点数计算单元加速 纹理 的处理。
GPU 不喜欢 透明,所以所有的绘图一定要弄成不透明,对于圆角和阴影这些的可以截个伪透明的小图然后绘制上去。在layer的回调里一定也只做绘图,不做计算!

UITableView性能优化相关推荐

  1. UITableView性能优化与卡顿

    UITableView性能优化与卡顿问题 最常用的就是cell的重用, 注册重用标识符 如果不重用cell时,每当一个cell显示到屏幕上时,就会重新创建一个新的cell 如果有很多数据的时候,就会堆 ...

  2. UITableView性能优化 - 中级篇

    老实说,UITableView性能优化 这个话题,最经常遇到的还是在面试中,常见的回答例如: Cell复用机制 Cell高度预先计算 缓存Cell高度 圆角切割 等等. . . 进阶篇 最近遇到一个需 ...

  3. IOS UITableView性能优化

    1.关于UITableView性能的优化,很容易就让人想起UITableView的复用,那么除此之外呢?还有么有其他的方法能够优化用户的体验,或者说优化我们的设计的软件呢? 答案是:有! 一般我们在设 ...

  4. 【原/转】UITableview性能优化总结

    UITableView作为ios中使用最频繁的控件之一,其性能优化也是常常要面对的,尤其是当数据量偏大并且设备性能不足时.本文旨在总结tableview的几个性能优化tips,并且随着认识的深入,本文 ...

  5. [性能优化]UITableView性能优化的一点感悟及计算UILabel高度的新方法

    前言  在使用过程中发现,我们App的首页在快速滑动时会出现掉帧,以及在上拉加载更多时会抖动,因为首页模块是以前的同事写的,很多代码已不适应当前的需求,所以产生了优化的想法,优化主要分为以下几个方面: ...

  6. [性能优化]UITableView性能优化的一点感悟及计算UILabel高度的新方法 1

    前言 在使用过程中发现,我们App的首页在快速滑动时会出现掉帧,以及在上拉加载更多时会抖动,因为首页模块是以前的同事写的,很多代码已不适应当前的需求,所以产生了优化的想法,优化主要分为以下几个方面: ...

  7. UITableView 性能优化

    网络图片异步加载,SDWebImage. 文字直接 drawInRect/drawAtPoint 绘制,参考 ABTableViewCell,AdvancedTableViewCells. 本地图片也 ...

  8. UITableView性能提升和优化(第3章) 之一

    在本章,你将做下面这些事情: 在实例中使用第2章介绍的测试工具 在例子中一步一步的对滚动性能进行优化 使用以下技术对UITableView进行优化 1)  使用基本的技术优化UITableView中简 ...

  9. UITableVIew的性能优化-重用原理

    UITableVIew的性能优化:使用方法创建cell时,先优先从缓存池中找cell,找不到再创建新的cell,并且要绑定Identifer标示. 代码: -(UITableViewCell *)ta ...

最新文章

  1. git常用基本简单命令
  2. python安卓版下载安装-python手册中文版apk下载
  3. Android数据存储之SQLite的操作
  4. [swift] Async
  5. ec200s 封装_什么是无闪退免签封装?免签封装如何实现?
  6. 关于 【通过代理访问】 的研究,【突破 IP ,“无限制”投票】
  7. 敏捷软件开发宣言–Manifesto for Agile Software Development
  8. 日语学习-多邻国-关卡1-介绍2
  9. hdfs shell
  10. Mysql学习总结(73)——MySQL 查询A表存在B表不存在的数据SQL总结
  11. 根据mac地址获取生产厂商
  12. Zemax操作--2(单透镜和双胶合透镜优化)
  13. *1179 筛选素数
  14. 基于turtle库用python画太极图案
  15. Python图像处理一:图像的读取、显示与存储
  16. 转:MySQL 的 my.cnf 文件(解决 5.7.18 下没有 my-default.cnf )
  17. 时光不负有心人 --又是折腾的一年
  18. Extracting and Composing Robust Features with Denoising Autoencoders论文笔记
  19. 怎样在xampp中使用mysql以及配置xampp
  20. CDN和CDN加速有什么关联

热门文章

  1. 大疆A型板使用经验分享(八)——FreeRTOS操作系统的使用
  2. FastJSON处理对象中属性值为空的数据
  3. unity制作滚动的天空简易版(在b站学的,此处总结,供学习)
  4. android adb 存储权限,android adb 权限修改
  5. 常用传感器讲解十--光传感器根据亮度安排灯光
  6. 关于SCO Unix 串口通讯
  7. h5 php登录注册页面验证,H5制作一个注册页面的代码实例
  8. [React]网易云音乐Web PC端
  9. 微信小程序怎么推广运营-微信小程序引流方法
  10. 思科关闭日志_关于思科交换机的日志配置总结