iOS程序性能优化的技巧

1. 用ARC管理内存

ARC(Automatic ReferenceCounting, 自动引用计数)和iOS5一起发布,它避免了最常见的也就是经常是由于我们忘记释放内存所造成的内存泄露。它自动为你管理retain和release的过程,所以你就不必去手动干预了。忘掉代码段结尾的release简直像记得吃饭一样简单。而ARC会自动在底层为你做这些工作。除了帮你避免内存泄露,ARC还可以帮你提高性能,它能保证释放掉不再需要的对象的内存。

2.尽量把views设置为透明

如果你有透明的Views你应该设置它们的opaque属性为YES。

原因是这会使系统用一个最优的方式渲染这些views。这个简单的属性在IB或者代码里都可以设定。

Apple的文档对于为图片设置透明属性的描述是:

(opaque)这个属性给渲染系统提供了一个如何处理这个view的提示。如果设为YES,渲染系统就认为这个view是完全不透明的,这使得渲染系统优化一些渲染过程和提高性能。如果设置为NO,渲染系统正常地和其它内容组成这个View。默认值是YES。

在相对比较静止的画面中,设置这个属性不会有太大影响。然而当这个view嵌在scroll view里边,或者是一个复杂动画的一部分,不设置这个属性的话会在很大程度上影响app的性能。

你可以在模拟器中用Debug\Color Blended Layers选项来发现哪些view没有被设置为opaque。目标就是,能设为opaque的就全设为opaque!

这里有一点需要注意,只要是有中文字符的Label,哪怕你设置成不透明,模拟器中这个Label依然会变红,这个猜测是字符绘制的时候出的问题,这个目前没找到好的解决方法。

3.避免过于庞大的XIB

iOS5中加入的Storyboards(分镜)正在快速取代XIB。然而XIB在一些场景中仍然很有用。比如你的app需要适应iOS5之前的设备,或者你有一个自定义的可重用的view,你就不可避免地要用到他们。

如果你不得不XIB的话,使他们尽量简单。尝试为每个Controller配置一个单独的XIB,尽可能把一个View Controller的view层次结构分散到单独的XIB中去。

需要注意的是,当你加载一个XIB的时候所有内容都被放在了内存里,包括任何图片。如果有一个不会即刻用到的view,你这就是在浪费宝贵的内存资源了。Storyboards就是另一码事儿了,storyboard仅在需要时实例化一个view controller.

当家在XIB是,所有图片都被chache,如果你在做OS X开发的话,声音文件也是。Apple在相关文档中的记述是:

当你加载一个引用了图片或者声音资源的nib时,nib加载代码会把图片和声音文件写进内存。在OS X中,图片和声音资源被缓存在named cache中以便将来用到时获取。在iOS中,仅图片资源会被存进named caches。取决于你所在的平台,使用NSImage 或UIImage的imageNamed:方法来获取图片资源。

这个问题我深有体会,用xib写的界面加载速度比直接用代码写的要慢好多

4. 在Image Views中调整图片大小

如果要在UIImageView中显示一个来自bundle的图片,你应保证图片的大小和UIImageView的大小相同。在运行中缩放图片是很耗费资源的,特别是UIImageView嵌套在UIScrollView中的情况下。

如果图片是从远端服务加载的你不能控制图片大小,比如在下载前调整到合适大小的话,你可以在下载完成后,最好是用background thread,缩放一次,然后在UIImageView中使用缩放后的图片。

5. 选择正确的Collection

学会选择对业务场景最合适的类或者对象是写出能效高的代码的基础。当处理collections时这句话尤其正确。

一些常见collection的总结:

Arrays: 有序的一组值。使用index来lookup很快,使用value lookup很慢,插入/删除很慢。

Dictionaries: 存储键值对。用键来查找比较快。

Sets: 无序的一组值。用值来查找很快,插入/删除很快。因为Set用到了哈希,所以插入删除查找速度比Array快很多

6. 打开gzip压缩

大量app依赖于远端资源和第三方API,你可能会开发一个需要从远端下载XML, JSON, HTML或者其它格式的app。

问题是我们的目标是移动设备,因此你就不能指望网络状况有多好。一个用户现在还在edge网络,下一分钟可能就切换到了3G。不论什么场景,你肯定不想让你的用户等太长时间。

减小文档的一个方式就是在服务端和你的app中打开gzip。这对于文字这种能有更高压缩率的数据来说会有更显著的效用。

好消息是,iOS已经在NSURLConnection中默认支持了gzip压缩,当然AFNetworking这些基于它的框架亦然。像Google App Engine这些云服务提供者也已经支持了压缩输出。

7. 重用和延迟加载(lazy load) Views

更多的view意味着更多的渲染,也就是更多的CPU和内存消耗,对于那种嵌套了很多view在UIScrollView里边的app更是如此。

这里我们用到的技巧就是模仿UITableView和UICollectionView的操作:不要一次创建所有的subview,而是当需要时才创建,当它们完成了使命,把他们放进一个可重用的队列中。

这样的话你就只需要在滚动发生时创建你的views,避免了不划算的内存分配。

创建views的能效问题也适用于你app的其它方面。想象一下一个用户点击一个按钮的时候需要呈现一个view的场景。有两种实现方法:

  1. 创建并隐藏这个view当这个screen加载的时候,当需要时显示它;
  2. 当需要时才创建并展示。

每个方案都有其优缺点。用第一种方案的话因为你需要一开始就创建一个view并保持它直到不再使用,这就会更加消耗内存。然而这也会使你的app操作更敏感因为当用户点击按钮的时候它只需要改变一下这个view的可见性。

第二种方案则相反-消耗更少内存,但是会在点击按钮的时候比第一种稍显卡顿。

8.权衡渲染方法

在iOS中可以有很多方法做出漂亮的按钮。你可以用整幅的图片,可调大小的图片,或者可以用CALayer, CoreGraphics甚至OpenGL来画它们。当然每个不同的解决方法都有不同的复杂程度和相应的性能。

简单来说,就是用事先渲染好的图片更快一些,因为如此一来iOS就免去了创建一个图片再画东西上去然后显示在屏幕上的程序。问题是你需要把所有你需要用到的图片放到app的bundle里面,这样就增加了体积–这就是使用可变大小的图片更好的地方了:你可以省去一些不必要的空间,也不需要再为不同的元素(比如按钮)来做不同的图。

然而,使用图片也意味着你失去了使用代码调整图片的机动性,你需要一遍又一遍不断地重做他们,这样就很浪费时间了,而且你如果要做一个动画效果,虽然每幅图只是一些细节的变化你就需要很多的图片造成bundle大小的不断增大。

总得来说,你需要权衡一下利弊,到底是要性能能还是要bundle保持合适的大小。

9.处理内存警告

一旦系统内存过低,iOS会通知所有运行中app。在官方文档中是这样记述:

如果你的app收到了内存警告,它就需要尽可能释放更多的内存。最佳方式是移除对缓存,图片object和其他一些可以重创建的objects的strong references.

幸运的是,UIKit提供了几种收集低内存警告的方法:

在app delegate中使用applicationDidReceiveMemoryWarning:的方法

在你的自定义UIViewController的子类(subclass)中覆盖didReceiveMemoryWarning

注册并接收 UIApplicationDidReceiveMemoryWarningNotification的通知

一旦收到这类通知,你就需要释放任何不必要的内存使用。

例如,UIViewController的默认行为是移除一些不可见的view,它的一些子类则可以补充这个方法,删掉一些额外的数据结构。一个有图片缓存的app可以移除不在屏幕上显示的图片。

这样对内存警报的处理是很必要的,若不重视,你的app就可能被系统杀掉。

然而,当你一定要确认你所选择的object是可以被重现创建的来释放内存。一定要在开发中用模拟器中的内存提醒模拟去测试一下。

当然,现在iOS设备运行内存越来越大,这一点很难出现了

10. 使用Sprite Sheets

Sprite sheet可以让渲染速度加快,甚至比标准的屏幕渲染方法节省内存。

11.避免反复处理数据

许多应用需要从服务器加载功能所需的常为JSON或者XML格式的数据。在服务器端和客户端使用相同的数据结构很重要。在内存中操作数据使它们满足你的数据结构是开销很大的。

比如你需要数据来展示一个table view,最好直接从服务器取array结构的数据以避免额外的中间数据结构改变。

类似的,如果需要从特定key中取数据,那么就使用键值对的dictionary。

这一点在处理大量数据的时候极为重要,用空间换时间的方法也许是极好的。

12.选择正确的数据格式

从app和网络服务间传输数据有很多方案,最常见的就是JSON和XML。你需要选择对你的app来说最合适的一个。

解析JSON会比XML更快一些,JSON也通常更小更便于传输。从iOS5起有了官方内建的JSON deserialization就更加方便使用了。

但是XML也有XML的好处,比如使用SAX来解析XML就像解析本地文件一样,你不需像解析json一样等到整个文档下载完成才开始解析。当你处理很大的数据的时候就会极大地减低内存消耗和增加性能。

以上就是iOS程序性能优化的建议的详细内容,更多关于ios 程序性能优化的资料请关注其它相关文章!