App的性能优化可以说是伴随着整个app的成长,是没有止境的。任何一次需求的修改,都会给项目结构带来变化,都需要我们进行程序的优化。性能优化,我的理解就是做好每一个细节。将大问题分而化之为一个个小的问题,才更容易看清问题的关键。
1.网络性能
1>.将网络请求封装为单例。一般我们会对网络请求进行封装为一个工具类。最好是将网络请求作为一个单例。不要每次请求都去allow网络请求的对象。否则会造成内存泄漏。因为网络请求结束之后,创建出来的对象往往会忘记释放。
2.内存问题
在ARC时代解决了大部分的内存泄漏。但是仍然会出现这个问题:
1.循环引用
2.Core Animation对象手动释放。 CG/CF 开头的函数,有创建就要有释放,这样可以有效降低内存泄漏的风险。
3.UIwebview内存泄漏
3.主线程阻塞
用户的输入和UIkit的执行渲染都是需要在主线程。所以要保证app的流畅度就一定不要阻塞主线程。可以开辟新的线程执行耗时、耗能的操作:网络的同步请求,I/O操作、大量的运算、读写文件、解压缩等
4.离屏渲染
指的是GPU在当前屏幕缓冲区以外开辟了一个缓冲区进行渲染操作。意味着你的app的部分区域每一帧渲染了两次,造成了一定的性能损失。例如我们日程经常打交道的TableViewCell,因为TableViewCell的重绘是很频繁的(因为Cell的复用),如果Cell的内容不断变化,则Cell需要不断重绘,如果此时设置了cell.layer可光栅化。则会造成大量的离屏渲染,降低图形性能。
5.图片的处理
通常加载图片会用imageNamed来加载图片。此函数会缓存加载的image。所以在加载使用一次的应用图片可以使用initWithContentsOfFile函数,以文件的形式去加载图片。
app的优化技术就是在减少内存使用,主线程减负,空间换时间等等,基于这些策略及技术考虑选择优化的方向。如:
1.避免对UIview透明。原因是透明性对性能要求较高。如果在滚动时页面比较复杂,体验上的差异会相对明显。
2.避免过于庞大的xib,视情况而定,将试图拆分为小的xib。当你加载一个xib的时候,所有内容都被放在了内存里,包括图片。如果有一个不会立即用到的view,那就浪费了这一部分资源了。
3.使图片符合UIImageView的尺寸。不要在运行的时候再让UIImageView自行压缩。这样会降低运行时的性能。
4.选择合适的collection,数据结构决定了算法的效率。如:使用Array使用下标签查找比较快,但是插入和删除较慢。set进行插入、删除较快。
5.使用缓存。对于时效性要求不高的数据完全可以使用缓存来保证快速显示。如:URL对应的图片缓存,通过数据库或者coreData来保存不需要变动的数据。使用NSCache进行数据或者图片的缓存,NSCache在收到内存警告的时候会主动释放当前界面没有使用的缓存数据,而且NSCache是线程安全的。
6.处理低内存警告。
7.重用一些高消耗的对象。如:NSDateFormatter,NSCalender等。可以将其作为属性或者静态变量进行使用。
8.在临时创建大量对象时,使用NSAutoreleasepool,例如,一个循环用于创建包含多个对象的数组,在循环体内,即可使用@autoreleasepool包裹创建代码。使用系统的@autoreleasepool会有延迟,内存不会马上释放。
9.对于排版复杂的文字或者图文混排,使用coreText技术。
10.在对渲染的效率要求较高的页面中,避免使用UILabel、UITextView等在主线程中进行排版和绘制的控件。应自定义文本控件,用TextKit或者CoreText进行文本异步绘制。另外,还有facebook的AsyncDisplayKit框架可以采用。将绘制图像放在次线程中执行,如在次线程中使用 CGContext进行画图,在主线程中 layer.contents = img。图片和视图的大小避免超过4096*4096,因为这是目前iphone5到iphone6p以及ipad仅仅通过GPU就直接处理的纹理尺寸上限,否则就GPU就会提交CPU先处理,这样开销很大。
11.减少视图或者layer的层级数量。在有多个层级时,可以将多图合并成一张图,再渲染显示
12.电量消耗:减少耗电与流量的操作。GPS在获取用户位置之后,就行关闭。根据需求而定GPS定位的精确度等级,定位精确度越高,越耗电。
13.关于后台运行。进入后台后,即尽量减少内存占用、释放所有的共享资源(如Calender或address book),因为iOS会kill后台中内存消耗最多的或者进入后台还占用共享资源的进程。