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

Let`s begin!

治病就要先知道病因,我们先来分析一下影响tableview滚动性能的因素有哪些:

1
2
3
1、cellForRowAtIndexPath方法中处理了过多业务
2、tableviewCell的subview层级太复杂,做了大量透明处理
3、cell的height动态变化时计算方式不对

前面两点比较好理解,本文着重处理第三种情况。

想要对tableview做性能优化,只能从tableview的数据源方法入手,纵观这些方法,主要有两个方法可以为我们所用:cellForRow以及heightForRow。我们一一分析:

(1)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
2
- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath
(**iOS 7专用**)
但是有人说了,我早听别人说了,reloadData 方法尽量不要调用,因为它是全部刷新的,我插入新行都用 insertRowsAtIndexPaths:withRowAnimation: 删除也用 delete 那个,这个总行了吧?!
 
这样也不能忽略 height For Row At Index Path 这个回调的重要性。因为在每次插入或者删除一行后同样需要调用一遍 所有行 的这个回调方法!是所有行!你没看错,所有只是简单的减少一个代理方法的计算量,就可以明显的提升加载速度。
也许有人又要问了,我的应用都是动态的高度,就像微博那样的,不定数量的文字,可能还有图片,大小也不固定,这些怎么返回固定的高度啊?
 
我指的固定高度不是 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了。
 
(2)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 和独立的浮点数计算单元加速 纹理 的处理。
 

UITableView的性能优化的更多相关文章

  1. UITableView的性能优化1

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

  2. 关于UITableView的性能优化(历上最全面的优化分析)

    (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath ...

  3. UITableView的性能优化10个小技巧

    通常你会发现一个图片类的app会在一个imageView上做下面这些事情: 1  下载图片(主要的内容图片+用户头像图片)2  更新时间戳3  展示评论4  计算动态的cell的高度 Tip#1 学习 ...

  4. UITableView性能优化

    关于UITableView的性能优化,网络上也有一些总结.在这里就介绍下我们项目中遇到的问题以及对应的解决方法.相信我们遇到的问题也有一定的普适性,能够作为其他问题的优化方案. Instruments ...

  5. iOS_UITableView性能优化那些事

    UITableView在实际开发中使用频率实在是很高, 因此, UITableView的性能优化是必不可少的, 本文下面就略微总结一下UITableView性能优化那些事. 本文着重介绍具体方法, 原 ...

  6. iOS 程序性能优化

    前言 转载自:http://www.samirchen.com/ios-performance-optimization/ 程序性能优化不应该是一件放在功能完成之后的事,对性能的概念应该从我们一开始写 ...

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

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

  8. UITableView的使用及性能优化

    UITableView可谓是日常开发中最重要的控件之一,而使用UITableView最重要的在于性能优化.iOS设备的内存有限,如果用UITableView显示成千上万条数据,就需要成千上万个UITa ...

  9. UITableView使用总结和性能优化

    UITableView使用总结和性能优化    UITableView有两种风格:UITableViewStylePlain和UITableViewStyleGrouped.如 果我们查看UITabl ...

随机推荐

  1. PHP date()函数格式与用法汇总

    在页面的最前页加上 date_default_timezone_set("PRC");   /*把时间调到北京时间,php5默认为格林威治标准时间*/ date () a:   & ...

  2. js 图片转换为base64

    <input id="file" type="file"> <img id="img" style="max-h ...

  3. 基于FPGA的有限状态机浅析

    前言:状态机大法好,状态机几乎可以实现一切时序逻辑电路. 有限状态机(Finite State Machine, FSM),根据状态机的输出是否与输入有关,可分为Moore型状态机和Mealy型状态机 ...

  4. Python 学习之路

    这个是我学python以来,写的的第一个小游戏,写的不好 题目:石头剪刀布 主要有两个难度 在普通模式,电脑是随机出 在噩梦下,就是不管你出什么,电脑都会赢你,牛逼吧 #Author:陈浩彬 impo ...

  5. 机器学习 F1-Score 精确率 - P 准确率 -Acc 召回率 - R

    准确率 召回率 精确率 : 准确率->accuracy, 精确率->precision. 召回率-> recall. 三者很像,但是并不同,简单来说三者的目的对象并不相同. 大多时候 ...

  6. android studio 目录结构讲解

    android studio 目录结构讲解 src 毫无疑问,src目录是放置我们所有 Java代码的地方,它在这里的含义和普通 Java 项目下的 src目录是完全一样的,展开之后你将看到我们刚才创 ...

  7. 读取不标准的JSON数据

    正常的JSON数据 [      {"key":"UI","value":"UII"},      {"key ...

  8. springboot整合rabbitmq

    概述 RabbitMQ是一个开源的消息代理和队列服务器,用来通过普通协议在完全不同的应用之间共享数据,或者简单地将作业队列以便让分布式服务器进行处理. 它现实了AMQP协议,并且遵循Mozilla P ...

  9. 一些内存模型、并发、netty知识点的记录

    happens-before:描述内存可见性as-if-serial:无论怎么重排序,程序的运行结果不会改变 ReentrantLock依赖了队列同步器AQS,其实现方式是volatile变量的读写操 ...

  10. HttpClient(一)HttpClient抓取网页基本信息

    一.HttpClient简介 HttpClient 是 Apache Jakarta Common 下的子项目,可以用来提供高效的.最新的.功能丰富的支持 HTTP 协议的客户端编程工具包, 并且它支 ...