UITableView性能优化
关于UITableView
的性能优化,网络上也有一些总结。在这里就介绍下我们项目中遇到的问题以及对应的解决方法。相信我们遇到的问题也有一定的普适性,能够作为其他问题的优化方案。
Instruments
要对UITableView
的性能进行优化,有一个工具肯定是不能少的,那就是Instruments
,如果还不知道Instruments
,建议先去看看相应的Apple Docoment
。在开始着手优化你的UITableView
的时候,不妨先用Instruments
来看看你的UITableView
看看你的代码的瓶颈究竟在哪里,不要轻易的对代码下判断,耗时不耗时。这里有个例子,当时我发现我们项目中有一个UITableView
的滚动特别不顺畅,而这个UITableView
的cell
中的布局也确实很复杂,优化了一段时间后却发现滚动还是一样的不顺畅,打开Instruments
工具Profile
,立刻就发现了初始化Cell
的代码占据了大量的运行时间,第一反应就是Reuse Identifier
写错了。果不其然,查了一下xib
和代码中的Identifier
,哪位粗心程序猿同学没有两处的Identifier
设为一致,导致每次都重新生成了一个Cell
。
其实这是个非常简单的问题,但凡使用过UITableView
的人都知道要对Cell
进行重用。但是这却是在优化中特别容易被忽略的点,这个例子是为了说明使用Instruments
的重要性,它能给我们的优化带来很大的方便。
将属性设置代码放在正确的位置
再来谈谈另一个容易被忽略的点。也是对我们的项目Profile
的时候发现的问题。这可能与每个人的编码习惯以及编程经验有关。在我们的项目代码中,我发现CustomCell
方法中的某些属性设置操作在CustomCell
方法中占了很大一部分时间,比如利用layer设置圆角、设置阴影、设置遮罩、设置图片等操作。仔细阅读代码后发现,其实这部分代码完全可以提前到awakeFromNib
或者是init
方法中去,但是直接写到了CustomCell
方法中了,这就等于每次CellForRowAtIndexPath:
时就会运行这些方法,其实也可以归结到重用的问题中去。
异步加载
既然讲到了CustomCell
方法,就继续说几个可以在这里面优化的地方。iOS 6
之后在很多控件中,Apple
给我们提供了attributedText
方法,以前需要使用Core Text
才能完成的工作现在使用attributedText
方法就能简单的完成了,给我们提供了很大的便利。但是在优化的时候,发现attributedText
方法的耗时是非常大的,如果设置了图片作为attachment
,那么就更加耗时了。因为闭源的原因,也不清楚究竟是什么原因引起的。既然这么耗时,又无法避免,那就只能直面他了,刚正面!优化用到的方法也很简单,就是异步的去执行这些操作。开个异步队列(非主队列)去构建这个attributedString
,然后回到主队列里来设置attributedText
,因为在iOS中UI操作必须要在主线程中进行嘛,不然会造成不可预知的后果,这个不可预知的后果据我观察一般就是UI不会立马更新。那么这里又有一个常用的优化方法了,其实不只针对UITableView
,其他场合也能适用——把耗时的操作异步的去处理,然后回到主线程中更新UI。在我们的项目中,某些CustomCell
方法因为业务需求,需要访问Disk。显然,IO
操作是耗时大户,滑动的时候有明显的卡顿,也是采用了异步方式来处理的。
容易忽视的stringWithFormat:
在优化中,还发现了一个很隐蔽的问题。如果你的CustomCell
方法中有大量的stringWithFormat:
操作的话,你可能需要在字符串的优化上下点力气。因为不幸的是stringWithFormat:
操作也会造成不可忽视的开销,听起来很奇怪吧。当时我在Profile
的时候也惊呆了,为啥这个操作会造成性能瓶颈。幸好我们有解决方案。我们可以用C Style
的方式来构造我们的字符串!事实证明这能减少不小开销,如果你的CustomCell
方法中有大量的stringWithFormat:
方法,那么性能提升的效果应该非常明显。下面这段代码可以用来进行C
和ObjC
字符串的转换:
char cString[255]; // 这里要根据实际情况开辟大小
sprintf(string, "Click: %d", numberOfClick);
NSString *objCString = [[NNString alloc] initWithUTF8String:cString];
GIF
因为业务需求,需要在某些Cell
中添加GIF
图片,Gif
图片本来就比较吃资源,满屏的Cell
每个都有一个GIF
在动,想想就酸爽。一开始是使用FlAnimatedImage
在每个Cell
中添加一个GIF View
,居然也没人发现有问题(应该是发现有问题,但是觉得问题不大),直到第一版本上架了也没人发现。某天我没事在优化的时候发现我的iPhone 5s
已经烫的可以煎鸡蛋了,然后用Instruments
一跑,不跑不知道,一跑吓一跳,停留在这个UITableView
不操作的时候,FlAnimatedImage
一直在创建线程,不烧CPU才怪呢。因为这个GIF
还不算特别复杂,想了想可以自己画,然后用几个动画就能做出一样的效果,果断换了解决方案,换完之后简直顺畅。
不要忘记scrollViewDidScroll
我觉得这应该又是一个偷懒的结果。同样是在Instruments
里发现的问题,scrollViewDidScroll:
方法莫名其妙的占了很多运行时间。打开来一看,哦!原来是要记录每次用户滑动后停下的位置,显然放在scrollViewDidScroll:
里是不合适的,因为随便滚动一下,scrollViewDidScroll:
就调用了N次。果断转移代码,想了下丢到了scrollViewWillEndDragging:withVelocity:targetContentOffset:
代理方法中去了,利用这个targetContentOffset
就能解决啦。和CellForRowAtIndexPath:
方法一样,这个方法调用的频率也很高,迫不得已不在在里面放耗时的代码。
图片!图片!
图片一直是吃资源的大户,网络图片的异步加载应该算是使用UITableViewCell
的初级技术,所以这里讲的并不是图片的加载。圆角图片,相信都见过,四个角圆圆的那种矩形图片,看起来萌萌的。圆角的实现方式也有好多种:配合使用layer
的cornerRadius
和maskToBounds
来实现、使用Core Graphics
绘制(用UIBezierPath
添加Clip
)、使用图片遮罩等等。如果只有一个圆角图片,那么可能不会造成大的影响,但是如果每个Cell
中都有圆角图片,那么建议是采用图片遮罩的形式来实现,因为这种方法效率更高。
图片加载还有个小技巧就是当图片在异步加载的时候,图片所在的Cell
滚动出了屏幕,那么立马把这个下载的操作给Cancel
掉,避免不必要的资源消耗。
[UIImage imageNamed:]
的数据会缓存在内存中,而[UIImage imageWithContentOfFile:]
的数据则不会。如果你需要在Cell
中频繁的设置几个图片,那么在Cell
中使用一个UIImage
对象来保存住这些Image
,也会对性能有所提升。
以上是我在项目中遇到的一些UITableView
优化的问题。其实网上还有很多经验,这里摘抄一些作为记录,来源都在最后的Reference
中有给出。
- 减少
Subview
的个数和层级。使用一个UIView
并override
drawRect:
方法来绘制所有内容能够提升UITableView
的性能。主要是因为GPU
负责来rendering
和compositing
,层级多了之后CPU
需要做的合成工作变得复杂,所以可能还不如drawRect:
使用CPU
来绘制比较快,这其中的原因也很复杂,不是任何时候使用drawRect:
都能提升性能的。 而且一般并不推荐这么做,这里有非常详细的解答。 - 将
Subview
的opaque
属性设置为YES
(不透明了就告诉GPU
不用再渲染此view
下的图层了,GPU
在UITableView``scroll
的时候做了大量的工作) - 将
CALayer
的ShouldRasterize
设置为YES
(ShouldRasterize
告诉系统可以直接使用Cache的备份,如果View
的内容不会改变,可以使用,否则会有副作用) - 不要拉伸
Cell
中的图片。 - 如果是动态高度的
Cell
,可以想办法缓存Cell
的高度,避免每次计算。 - 使用
Instruments
找到当前的瓶颈是在CPU
还是GPU
上。链接 - 如果
Cell
有阴影,尽量使用图片而不是操作layer
来绘制。
除了以上技术上可以对UITableView
的性能进行优化外,还可以从加载逻辑上对UITableView
的性能进行优化。
这篇文章就从图片的加载逻辑上做了优化,达到提升性能的目的。 主要思想是:用户在滑动UITableView
时,不加载快速滑动过程中的图片,预先加载UITableView
滚动停下位置的图片。
UITableView性能优化的更多相关文章
- 【原/转】UITableview性能优化总结
UITableView作为ios中使用最频繁的控件之一,其性能优化也是常常要面对的,尤其是当数据量偏大并且设备性能不足时.本文旨在总结tableview的几个性能优化tips,并且随着认识的深入,本文 ...
- UITableView性能优化及手工绘制UITableViewCell
提高表视图的性能 UITableView作为应用中最常用的视图,它的性能优化问题几乎是经常提及.下面对在非网络访问情况下的表视图性能优化进行了主要的几点说明: 1.自定义类或XIB文件时 在系统提供的 ...
- UITableView性能优化【本文摘自智车芯官网】
UITableView是个表格视图,可以在表格行空间中添加多个子控件,UITableView继承了UIScrollView,默认状态下可以堆单元格进行滚动,所有的UITableViewControll ...
- uitableview性能优化(转)
这个感觉写的很好 收藏一下 以备后用 转自 http://www.cnblogs.com/pengyingh/articles/2354714.html 在iOS应用中,UITableView应该是使 ...
- iOS边练边学--UITableView性能优化之三种方式循环利用
一.cell的循环利用方式1: /** * 什么时候调用:每当有一个cell进入视野范围内就会调用 */ - (UITableViewCell *)tableView:(UITableView *)t ...
- UITableView 性能优化
网络图片异步加载,SDWebImage. 文字直接 drawInRect/drawAtPoint 绘制,参考 ABTableViewCell,AdvancedTableViewCells. 本地图片也 ...
- 【解决方法】UITableView 性能优化笔记
1.网络图片异步载入,SDWebImage. 2.文字直接 drawInRect/drawAtPoint 绘制,參考 ABTableViewCell.AdvancedTableViewCells. 3 ...
- iOS回顾笔记(07) -- UITableView的使用和性能优化
iOS回顾笔记(07) -- UITableView的使用和性能优化 如果问iOS中最重要的最常用的UI控件是什么,我觉得UITableView当之无愧!似乎所有常规APP都使用到了UITableVi ...
- iOS_UITableView性能优化那些事
UITableView在实际开发中使用频率实在是很高, 因此, UITableView的性能优化是必不可少的, 本文下面就略微总结一下UITableView性能优化那些事. 本文着重介绍具体方法, 原 ...
随机推荐
- fork()和vfork()区别
fork创建进程,子进程和父进程不一定谁先执行 vfork创建的进程,不分配新的资源,子进程用父进程相应的资源,且子进程先执行. 用vfork创建的进程,资源共享,那么,数据是不是不牵扯通信间的机制, ...
- Annotation【转】
1.Annotation的工作原理: JDK5.0中提供了注解的功能,允许开发者定义和使用自己的注解类型.该功能由一个定义注解类型的语法和描述一个注解声明的语法,读取注解的API,一个使用注解修饰的c ...
- VS2005下开发PPC2003和WM50编译器一些设置
1.vs2005开发WM5时,编译器和linker的选项配合问题 链接:http://www.mivi.name/blog/index_en.php?itemid=258 首先说ARM4 ARM4T ...
- xcopy 复制了0个文件
xcopy /Y "..\..\..\SolutionItems\zbmyuncore.db" "..\ZITaker" 复制zbmyuncore.db文件的时 ...
- Ubuntu安装已经下载好的文件包
默认的文件下载都在 ~/Downloads 文件夹里面. 按 ctrl+alt+t 打开命令. 1.解压下载好的文件包,如: tar -xvf Sublime\ Text\ 2.0.2.tar.bz2 ...
- 1210. Kind Spirits(spfa)
1210 简单模版题 敲个spfa还得瞟下模版.. #include <iostream> #include<cstdio> #include<cstring> # ...
- POJ 2586 Y2K Accounting Bug(贪心)
题目连接:http://poj.org/problem?id=2586 题意:次(1-5.2-6.3-7.4-8.5-9.6-10.7-11.8-12),次统计的结果全部是亏空(盈利-亏空<0) ...
- POJ3921
搜索 每次找出最短路 如果小于等于k 那么必定这里有一点是要被删掉的 枚举这个最短路径上的每一个点 (一般不会超过20) 将其相邻边删除 用dijskra求最短路径并且保存即可 深度搜索 #inclu ...
- Codeforces 374A - Inna and Pink Pony
原题地址:http://codeforces.com/contest/374/problem/A 好久没写题目总结了,最近状态十分不好,无论是写程序还是写作业还是精神面貌……NOIP挂了之后总觉得缺乏 ...
- 【转】 实现 Cocos2d-x 全局定时器
转自:http://www.tairan.com/archives/3998 cocos2d-x 中有自己的定时器实现,一般用法是在场景,层等内部实现,定时器的生命周期随着它们的消亡而消亡,就运行周期 ...