IOS 性能优化

最近工作比较空闲,相信我不说大家都知道性能优化的重要性了吧,很多面试公司都有的要求。这也是作为一个高级软件开发工程师的必备技能 。

zero 卡顿是我们经常遇到的问题,这里就要提到GPU/CPU了

1.为什么会卡顿,在此期间GPU/CPU都做了哪些工作呐?

  • CPU:对象的创建/销毁/属性的调整/布局计算/文本的计算和排版/图片格式转换和解码,图像的绘制
  • GPU 图像处理器,主要进行纹理的渲染。(纹理是GPU所能识别的一种图像格式)
  • IOS是双缓存机制,包括前帧缓存,后帧缓存
  • CPU通过一系列的计算,然后GPU去渲染,通过帧缓存之后被视频控制器读取,最后显示到屏幕上。成像的原理是通过水平同步信号+垂直同步信号一帧帧的绘制而成。
  • 卡顿的原因:由于CPU要先计算-GPU渲染,假如CPU/GPU处理的事情较多,在固定的帧率下,未完成需要处理的事情,此时垂直同步信号已经到来,两者交叉就会造成视觉上的卡顿

2.卡顿优化

  • 尽量减少CPU/GPU的资源消耗
  • 不要频繁的调用UIView的相关属性,如frame/bounds/tranform等
  • 尽量提前计算好布局,在有需要的时候一次性调整对应的属性
  • 尽量吧耗时操作(文本尺寸计算/绘制,图片解码/绘制)放到子线程处理,同时我们在处理线程的时候要注意线程的最大并发数量

one  tableView的缓存


1.说到缓存,大家想到的是不是tableviewcell的缓存机制呐
TableViewCell 复用
cellForRowAtIndexPath:回调的时候只创建实例,快速返回cell,不绑定数据。在willDisplayCell: forRowAtIndexPath:的时候绑定数据(赋值)。

2.TableViewCell 

tableView滑动时,会不断调用heightForRowAtIndexPath:,当 cell 高度需要自适应时,每次回调都要计算高度,会导致 UI 卡顿。为了避免重复无意义的计算,需要缓存高度。

怎么缓存

  • 字典,NSCache。它可以自动清理系统占用内存且是线程安全的。自动清理时机:往cache内添加新内容时,以及发生内存警告时。
  • UITableView-FDTemplateLayoutCell(AutoLayout布局)
  • 缓存高度可以避免无意义的计算。自适应高度的计算。推荐sunny的一篇文章

Two  内存问题

1.常见的问题如下:循环引用,webView的内存泄漏

在IOS 4.2 以后苹果引用了ARC,但是ARC本质与MRC一致,都是通过引用计数管理内存的。但是ARC也不是万能的。也会为了程序的正常运行,会隐式的持有或复制对象。这样变容易造成内存泄漏。其中最常见的就是block的循环引用问题(解决方法这里我就不多解释了)

2.AFnetworking 的内存泄漏问题

使用AF的都知道,需要使用到AFHTTPSessionManager的实例对象。 [AFHTTPSessionManager manager] 我一般都是这样获取的,不知道你们是怎样获取的。但是通过Instrcument工具分析,看到他会出现内存泄漏。解决方法如下:

2.1 给它写个单例

+ (AFHTTPSessionManager *)sharedHTTPSession{
    static AFHTTPSessionManager *manager = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        manager = [AFHTTPSessionManager manager];
    return manager;
}

2.2 demo推荐的使用方法

@import AFNetworking;

@interface AFAppDotNetAPIClient : AFHTTPSessionManager

+ (instancetype)sharedClient;

@end

#import "AFAppDotNetAPIClient.h"

static NSString * const AFAppDotNetAPIBaseURLString = @"https://api.app.net/";

@implementation AFAppDotNetAPIClient

+ (instancetype)sharedClient {
    static AFAppDotNetAPIClient *_sharedClient = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
   _sharedClient = [[AFAppDotNetAPIClient alloc] initWithBaseURL:[NSURL URLWithString:AFAppDotNetAPIBaseURLString]];
       _sharedClient.securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeNone];
    });
    
    return _sharedClient;
3.避免主线程堵塞

     在主线程中避免复杂的计算堵塞主线程,造成卡顿

4.图片的处理

通常imageNamed :加载mainbundle图片时,函数会缓存加载的image。对于那么使用较少的图片,消耗内存较大 ,所以启动图片设置时,建议使用initWithContentsOfFile:函数。

5.  重用开销大的对象

NSDateFormatter/NSCalendar  特别消耗内存,因为他们的初始化很慢。所以你可以在类中申明一个属性或者懒加载一个他们的实例。

6.选择合适的数据存储

  • 使用`NSUerDefaults`-只能用来存储小数据
  • 使用XML, JSON, 或者 plist - XML 需要读取整个文件到内存里去解析
  • 使用NSCoding存档- 需要读取文件
  • 使用类似SQLite的本地SQL数据库
  • 使用 Core Data - 苹果建议使用。与SQLite相比性能没啥区别。如果使用SQLite的话建议看下Realm框架。

7.启动时间(这个会在APP启动优化详细介绍)

启动时间很重要,就像人的第一印象,避免启动页中使用庞大的XIB。尽量避免耗时操作,如果需要数据请求的话,尽量在子线程进行

8.学会处理内存警告

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

  • 在app delegate中使用`applicationDidReceiveMemoryWarning:` 的方法
  • 在你的自定义UIViewController的子类(subclass)中覆盖`didReceiveMemoryWarning`
  • 注册并接收 UIApplicationDidReceiveMemoryWarningNotification 的通知

在这些方法中处理,比如清掉缓存,否则的话会被系统干掉你的应用。

耗电优化

1.耗电的主要来源

  • 图像处理
  • 定位服务
  • 网络请求
  • CPU处理

2.耗电优化

  • 图片设置圆角的时候尽量让美工提供图片,使用maskToBounds及layer.clipToBounds都会有很大的资源消耗
  • 一直在后台定位刷新位置
  • 减少定时器的使用
  • 减少I/O操作,不要频繁写入小数据,尽量一次读取。读取大数据时可以使用dispatch_io,它会优化磁盘访问。数据量较大时,建议使用数据库。
  • 网络优化:减少网络请求的次数,如果数据多次都是相同建议使用缓存。使用断点续传下载数据。让用户取消长时间运行或者网络慢的网络操作,设置合适的网络超时时间。

猜你喜欢

转载自blog.csdn.net/qq_33726122/article/details/80983125