文章出出:http://www.code4app.com/blog-826368-158.html
应用程序中的性能对 iOS 应用的开发来说尤其重要,如果一个应用失去反应或者很慢,失望的用户会把他们的失望写满App Store的评论。然而由于iOS设备的限制,想处理好应用程序中的性能是一件难事。我们在开发过程中会有很多地方是需要注意的,当然也很容易在做出选择时忘记考虑性能影响。
我们在开发中常见的错误就是没有给UITableViewCells, UICollectionViewCells,甚至是UITableViewHeaderFooterViews设置正确的reuseIdentifier。
在优化性能时,table view用 `tableView:cellForRowAtIndexPath:` 为rows分配cells的时候,它的数据应该重用自UITableViewCell。 一个table view维持一个队列的数据可重用的UITableViewCell对象。当然如果不使用reuseIdentifier的话,每显示一行table view就需要设置全新的cell。这样一来对应用程序性能的影响非常的大,特别会使app的滚动体验大大的降低。
从iOS6起,除了对UICollectionView的cells和补充views,也应该在header和footer views中使用reuseIdentifiers,使用reuseIdentifiers的话,在一个table view中添加一个新的cell时在data source 方法中添加这个方法:
static NSString *ID = @"MyCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
这个方法可以把那些已经存在的cell从队列中排除,或者在必要时使用先前注册的nib或者class创造新的cell。如果没有可重用的cell,也没有注册一个class或者nib的话,这个方法就会返回nil。
2、在开发的过程中要尽量把Views设置为透明色:
如果应用中有透明的Views我们应该设置它们的opaque属性为YES。
其原因是这样会使系统用一个最优的方式渲染这些views。这个属性在IB或者代码里都可以设定。
Apple的文档对于为图片设置透明属性的描述是:
(opaque)这个属性给渲染系统提供了一个如何处理这个view的提示。如果设为YES, 渲染系统就认为这个view是完全不透明的,这使得渲染系统优化一些渲染过程和提高性能。如果设置为NO,渲染系统正常地和其它内容组成这个View。默认值是YES。
在相对比较静止的画面中,设置这个属性不会有太大影响。然而当这个view嵌在scroll view里边,或者是一个复杂动画的一部分,不设置这个属性的话会在很大程度上影响app的性能。所以我们可以在模拟器中用DebugColor Blended Layers选项来发现哪些view没有被设置为opaque。目标就是,能设为opaque的就全设为opaque!
如果图片是从远端服务加载的你不能控制图片大小,比如在下载前调整到合适大小的话,你可以在下载完成后,最好是用background thread,缩放一次,然后在UIImageView中使用缩放后的图片。
但是使用XML也有XML的好处,比如使用SAX 来解析XML就像解析本地文件一样,我们不需像解析json一样等到整个文档下载完成才开始解析,那么当我们处理很大的数据的时候就会极大地减低内存消耗和增加性能。
XML的解析方式:
①DOM解析:是将文档一次性全部下载到本地在按节点进行解析,这样对我们的应用程序的内存消耗极大,手机本身的内存就不是很大,不像电脑那样有很大的内存,可见这种解析方式不太适用于手机,即手机无法直接使用 DOM 的方式来解析 XML;
②SAX解析:是一种只读的方式,在文档中按照节点从上之下的方式来进行解析,是苹果提供的解析方式,虽然节点是一次性读取的,但是节点中的内容是多次读取的,这种解析方式的速度相当的快,可以用 NSXMLParser 通过 代理 方法来实现解析;
SAX解析方式的步骤:
①开始文档—准备工作
②开始"节点"
③发现节点内部的内容,每一个节点,可能都需要多次解析才能完成
④结束"节点"
⑤结束文档—解析结束
以上步骤,②、③、④会不断循环,一直到所有的解析完成。
5、避免反复处理数据:
我们的应用需要从服务器加载所需的常用的JSON或者XML格式的数据。在服务器端和客户端使用相同的数据结构很重要。在内存中操作数据使它们满足我们的数据结构开销很大的。
譬如我们需要数据来展示一个table view,最好直接从服务器取array结构的数据以避免额外的中间数据结构改变。相似的,如果需要从特定key中取数据,那么就使用键值对的dictionary。
6、对tableView的优化:
Table view需要有很好的滚动性能,要不用户会在滚动过程中发现动画的弊端,为了保证table view能够平滑滚动,我们可以采取以下的措施:
- · 正确使用`reuseIdentifier`来重用cells
- · 尽量使所有的view opaque,包括cell自身
- · 避免渐变,图片缩放,后台选人
- · 缓存行高
- · 如果cell内现实的内容来自web,使用异步加载,缓存请求结果
- · 使用`shadowPath`来画阴影
- · 减少subviews的数量
- · 尽量不适用`cellForRowAtIndexPath:`,如果你需要用到它,只用一次然后缓存结果
- · 使用正确的数据结构来存储数据
使用`rowHeight`, `sectionFooterHeight` 和 `sectionHeaderHeight`来设定固定的高,不要请求delegate
7、用户响应:
①用户响应,即APP用户所触发的操作都能得到立刻响应,即用户事件能够被主线程的Run Loop得到及时的处理;
②要让主线程的Run Loop更好的响应用户的事件,我们应该尽量减少在主线程做复杂的操作的时间,尤其是I/O操作,网络操作,大量复杂的运算等,这类操作务必不要在主线程中执行。
8、内存管理的优化:
①合理的利用缓存机制,可以有效的减小设备内存的占用率,从而来降低内存溢出的概率和崩溃率; ②及时的处理内存警告; ③对大数据的内存管理:从网络中获取的大文件不要直接保存到内存中,可以合理的利用沙盒的缓存机制,来减小对内存的压力; ④大量的循环创建临时变量时的内存管理:如果需要大量的且循环的创建临时的变量,我们就需要在循环开始的时候就创建自动释放池; ⑤对图片/大文件的压缩处理:我们在做图片上传的时候,可以先把图片压缩后在保存或者上传; ⑥减少UIWebView的应用:因为其对内存的占用率是相当高的。
9、对数据压缩:大的数据可以采用压缩返回,减少用户流量的消耗,加快APP的反映速度
10、对数据库的优化:①在数据库的设计上面可以做一些重构; ②对查询语句的一些优化; ③如果数据过多,我们可以把其分成不同的表或者库
11、从代码的规范上: ①这个可以用隐形的方式来提高APP的性能,譬如:用if else 还是用 Switch; ②CodeReview(要坚持用CodeReview来对代码进行持续的重构,从而减少代码的逻辑复杂度)。
12、要避免过于使用庞大的XIB:XIB和StoryBoard的本质就是XML文件,解析这样的文件是相当的耗费性能的。
13、对重用的View进行封装:如果过多的创建View的话,就意味着会消耗更多的性能,所以要对重用的View进行封装
14、避免进行大量的日期格式的转换:频繁的转换日期的格式对APP来说消耗的性能也是很大的
15、对控件的渲染:如果要做一个特殊样式的按钮的话,我们可以事先将渲染好的图片设置到按钮上,这个图片放在Bundle里面,然后跟着我们的APP进行一起打包,这样就避免了画个图形让后再显示到APP的屏幕上去。