一、应用启动优化
APP 启动过程中,应尽量减少不必要的操作,从而缩短应用的启动时长。
1、首次启动
1.确定在展示 UI 前必须执行的任务。没有必要加载的功能和用户偏好不进行加载。崩溃报告系统应该第一个被初始化。
2.按顺序执行任务。
日志、统计等必须在 APP 一起动就最先配置的事件
项目配置、环境配置、用户信息的初始化 、推送、IM等事件
其他 SDK 和配置事件
3.将任务拆分为两类:一类是必须在主线程中执行的任务,另一类是可以在其他线程中执行的任务 ,然后分别执行。还可以进一步将在非主线程中执行的任务分为可以并发执行的和不能并发执行的。
4.其他任务可以在加载 UI 后执行或异步执行。延迟其他不必要的初始化。(例如,写日志消息或跟踪事件)
2、main()函数之前耗时的影响因素
动态库加载越多,启动越慢。
ObjC类越多,启动越慢。
rootViewController及其childViewController的加载、view及其subviews的加载越多,启动越慢。
二、用户界面
1、卡顿的原因一般有三个:
UI对象的创建,属性修改
布局
渲染
2、卡顿解决的主要思路
尽可能减少CPU、GPU资源消耗
一般FPS达到60FPS就会感觉不到卡顿,按照60FPS的刷帧率,每隔16ms就会有一次VSync信号(1000ms / 60 = 16.667ms)
3、 卡顿优化 CPU
1、尽量用轻量级的对象,比如用不到事件处理的地方,可以考虑使用CALayer取代UIView,能用int就不用NSNumber。
2、不要频繁地调用UIView的相关属性,比如frame、bounds、transform等属性,尽量减少不必要的修改,因为每次修改都要重新计算和渲染,消耗性能比较多。
3、尽量提前计算好布局,在有需要时一次性调整对应的属性,不要多次修改属性,因为多次修改也会重新计算和渲染。
4、Autolayout会比直接设置frame消耗更多的CPU资源,因为Autolayout本身性能就不是很高。
5、图片的size最好刚好跟UIImageView的size保持一致,如果不一致CPU就会对图片进行伸缩操作,这样比较消耗CPU资源。
6、控制一下线程的最大并发数量,不要无限制的并发,这样会让CPU很忙。
7、尽量把耗时的操作放到子线程,这样可以充分利用CPU的多核,这样CPU的资源消耗分担的也比较合理。
4、比较耗时的操作
1.文本处理(尺寸计算、绘制):计算文字宽高是可以放到子线程去计算的,或者drawWithRect文本绘制,也是可以放到子线程去绘制。
图片处理(解码、绘制)
2.通过imageNamed加载图片,加载完成后是不会直接显示到屏幕上面的,因为加载后的是经过压缩的图片二进制,当真正想要渲染到屏幕上的时候再拿到图片二进制解码成屏幕显示所需要的那种格式,然后渲染显示,而这种解码一般默认是在主线程操作的,如果图片数据比较多比较大的话也会产生卡顿。一般我们的做法是在子线程提前解码图片二进制。
5. 卡顿优化 GPU
1.尽量避免短时间内大量图片的显示,尽可能将多张图片合成一张进行显示,这样只渲染一张图片,渲染更快。
2.GPU能处理的最大纹理尺寸是4096x4096,一旦超过这个尺寸,就会占用CPU资源进行处理,所以纹理尽量不要超过这个尺寸。
3.尽量减少视图数量和层级,视图层级太多会增加渲染时间。
4.减少透明的视图(alpha<1),不透明的就设置opaque为YES,因为一旦有透明的视图就会进行很多混合计算增加渲染的资源消耗。
5.尽量避免出现离屏渲染
6、为什么离屏渲染消耗性能?
1.需要创建新的缓冲区
2.离屏渲染的整个过程,需要多次切换上下文环境。先是从当前屏幕(On-Screen)切换到离屏(Off-Screen),等到离屏渲染结束以后,想要将离屏缓冲区的渲染结果显示到当前屏幕上,就又需要将上下文环境从离屏切换到当前屏幕。
7、哪些操作会触发离屏渲染?
光栅化:layer.shouldRasterize = YES
遮罩:layer.mask
圆角:同时设置layer.masksToBounds = YES、layer.cornerRadius大于0
可以考虑通过CoreGraphics绘制裁剪圆角,或者叫美工提供圆角图片
阴影:layer.shadowXXX
如果设置了layer.shadowPath就不会产生离屏渲染
三、耗电优化
1、影响电量的五个因素
Network : 网络活动会唤起需要长时间周期性供电的无线电模组,可以分批次进行网络请求,来降低开销.
Location :精密&高频的的定位会增加开销,需要按需使用.
CPU :CPU使用率超过20%就会快速耗干电池电量.高效使用CPU,并且当用户出现模糊输入时快速做出不做事情的反应.
GPU :图形处理器(显卡的处理器),乱使用GPU会导致交互差,并且降低电池寿命.
Background : 后台状态App仍会消耗电量,App要按需执行后台操作,并使用延迟APIs来保证系统运算高效执行.另外,在app进入后台状态是,立即减少动作,并且通知系统一次这些动作已经完成.
耗电量优化
2、网络方面优化
请求前判断网络状态,网络不可用,不要尝试执行网络请求;
请求前设置合适的超时时间,避免长时间运行或者速度很慢的网络操作,
请求过程尽量使用断点续传,否则网络不稳定的时候可能多次传输相同的内容。(传输1M文件,如果一次性下载,一旦网络问题下载失败,下次重新请求,会从头开始。之前下载过的部分会进行重新下载,断点续传可以保证之前下载的数据缓存起来);
减少、压缩网络数据。(不同格式数据提交关系:XML提交比较大;JSON 提交比较小,protobuf提交最小)
请求结果使用缓存
批量传输,避免多次WIFI多次上电吊电。比如下载视频流时,不要传输很小的数据包,直接下载整个文件或者一大块一大块地下载。如果下载广告,一次性多下载一些,然后再慢慢展示。如果下载电子邮件,一次下载多封,不要一封一封地下载。
3、定位优化
如果不是导航的应用,尽量不要实时更新位置,定位完毕就关掉定位服务;
如果只是需要快速确定用户的位置,最好用CLLocationManager的requestLocation方法。定位完成后,会自动让定位硬件断电;
尽量降低定位精度,比如尽量不要使用精度最高的KCLLocationAccuracyBest;精度越高,硬件模块功耗越大;
需要后台定位时,尽量设置pauseLocationUpdatesAutomatically为YES,如果用户不太可能移动的时候系统会自动暂停位置更新。
尽量不要使用startMonitoringSignificantLocationChanges,优先考虑startMonitoringForRegion:
4、代码层面
1.合理使用NSDateFormatter 和 NSCalendar这种高开销对象
性能测试表明,NSDateFormatter的性能瓶颈是由于NSDate格式到NSString格式的转化,所以把NSDateFormatter创建单例意义不大.推荐的做法是,把最常用到的日期格式做缓存.
2.不要频繁的刷新页面,能刷新1行cell最好只刷新一行,尽量不要使用reloadData.
3.选择正确的集合
NSArray,使用index来查找很快(插入和删除很慢)
NSDictionary字典,使用键来查找很快
NSSets,是无序的,用键查找很快,插入/删除很快
4.少用运算获得圆角,不论view.maskToBounds还是layer.clipToBounds都会有很大的资源开销,必须要用圆角的话,不如把图片本身就做成圆角
5.懒加载,不要一次性创建所有的subview,而是需要时才创建.
6.重用
7.图片处理
图片与imageView相同大小,避免多余运算
可以使用整副的图片,增加应用体积,但是节省CPU
可调大小的图片,可以省去一些不必要的空间
= CALayer,CoreGraphics,甚至OpenGL来绘制,消耗CPU
8.cache,cache,cache(缓存所有需要的)
网络请求增加缓存
复杂计算结果的缓存(UITableView的行高)
9.尽量少用透明或半透明,会产生额外的运算.
10.使用ARC减少内存失误,dealloc需要重写并对属性置为nil
11.避免庞大的xib,storyBoard,尽量使用纯代码开发
5、CPU层面
1.Timer的时间间隔不宜太短,满足需求即可
2.线程适量,不宜过多,不要阻塞主线程
3.优化算法,减少循环次数
4.定位和蓝牙按需取用,定位之后要关闭或降低定位频率
四、App瘦身
iOS该怎么瘦身
1、删除无用的图片资源。
2、对资源图片压缩。
3、去除无用的OC类,去除无用的方法。出去无用的静态库。LinkMap的文件
https://www.jianshu.com/p/20a55ce120f9
https://www.jianshu.com/p/f3a44a16d4ea
https://www.jianshu.com/p/54d8640b0ff0
https://www.jianshu.com/p/20a55ce120f9