一、接口请求优化

在工程项目中,多个一级界面包含状态,如:服务入口的动态配置,未读消息数量,图片文字等,因此产品设计要每次切换 tab 时都请求数据,及时的更新页面状态。在实际开发中,频繁的调用接口,频繁的刷新界面显然是影响用户体验的,所以需要进行优化,优化的思路有以下几点:

  1. 使用 loading + 默认灰色矩形视图;
  2. 每隔 15s 以上才请求一次,防止频繁触发请求

    @property (nonatomic, assign) CFTimeInterval lastTi;
    - (void)viewWillAppear:(BOOL)animated
    {
    [super viewWillAppear:animated];
    CFTimeInterval nowTi = CACurrentMediaTime();
    if (self.lastTi <= 0 || nowTi - self.lastTi > 15) {
    [self makeRequestAction];
    self.lastTi = nowTi;
    }
    }
    - (void)makeRequestAction
    {
    // 接口请求
    }

    CACurrentMediaTime() 在退到后台、手动修改设备时间后没有影响。

  3. 对数据进行判断,数据没有更新不需要刷新界面。这里要注意,存储的是不是字符串,而是字符串的 hash 值,因为长度比较小。

    @property (nonatomic, assign) NSUInteger compareHash;  // 判断列表数据是否更新
    {
    NSUInteger hash = [data.mainTools componentsJoinedByString:@""].hash;
    if (self.compareHash == hash) {
    return;
    }
    self.compareHash = hash;
    // 更新界面
    }

这里的策略还是存在点问题:

  1. 不能处理好未读标识。比如当进入子界面详情时,这里需要更新未读状态,但因为 15s 的限制,而不能及时刷新;

二、界面优化

  1. 使用 Debug -> View Debugging -> Rendering 中的界面渲染选项,进行界面优化

  2. cell 滚动停止时加载

三、资源加载优化

  1. 图片加载

    imageNamed:

    利用它可以方便加载资源图片。用 imageNamed 的方式加载时,会把图像数据根据它的名字缓存在系统内存中,以提高 imageNamed 方法获得相同图片的 image 对象的性能。即使生成的对象被 autoReleasePool 释放了,这份缓存也不释放。而且没有明确的释放方法。如果图像比较大,或者图像比较多,用这种方式会消耗很大的内存。

    优点:加载图片速度快;
    缺点:耗内存大,适用于小图片并且会被频繁读取的图片。

    imageWithContentsOfFile:

    加载的图片是不会缓存的。得到的对象时 autoRelease 的,当 autoReleasePool 释放时才释放。

    优点:图片数据不缓存,节省内存;
    缺点:加载图片速度相对慢,每次读取图片都要从路径下寻找并解析图片数据。适用于会用到的图片数据不大,且不经常用到的。

    imageNamed: 加载会缓存在内存中,对于常用的图片可以放在 asset 里,不常用的图片放在 bundle 的路径下通过 imageWithContentsOfFile: 获取图片资源。

    initWithContentsOfFile:

    一般用在封面等图比较大的地方。适用于大图片,且不经常要用的图片。

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(4 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    for (int i = 0; i < 100000; i++) {
    self.loadImageView.image = [UIImage imageNamed:@"icon"];
    //self.loadImageView.image = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"icon" ofType:@"png"]];
    }
    });
    • imageNamed:


    • imageWithContentsOfFile:


    在有缓存的情况下,即使运行 100000 次,也不会等待很久,而 imageWithContentsOfFile: 会等待很久,且内存持续增长。

  2. UITableView 中使用 imageNamed: 加载图片,频繁上下滑动时 CPU 耗时不断增长。

    原本期望 imageNamed: 创建了缓存的,不应该持续耗费 cpu 时间,结果却耗费了 6-700ms,多处合起来有几秒。

    优化思路是自己使用 NSDictionary 或 NSCache 存储 images,使用时根据 key 来获取。

    // .h 文件
    FOUNDATION_EXTERN NSString * kAPlaceholderImageKey;
    FOUNDATION_EXTERN NSString * kBPlaceholderImageKey;
    - (UIImage *)imageForKey:(NSString *)placeholderImageKey;
    // .m 文件
    NSString * kAPlaceholderImageKey = @"APlaceholderImageKey";
    NSString * kBPlaceholderImageKey = @"BPlaceholderImageKey";
    - (UIImage *)imageForKey:(NSString *)placeholderImageKey
    {
    return [self.imageCache objectForKey:placeholderImageKey];
    }
    /**
    * @brief 缓存 cell 中需要重复使用的图片
    */
    - (NSCache *)imageCache
    {
    if (_imageCache == nil) {
    _imageCache = [[NSCache alloc] init];
    [_imageCache setObject:[UIImage imageNamed:@"1"] forKey:kAPlaceholderImageKey];
    [_imageCache setObject:[UIImage imageNamed:@"2"] forKey:kBPlaceholderImageKey];
    }
    return _imageCache;
    }

四、启动速度优化

Total pre-main time: 617.58 milliseconds (100.0%)
dylib loading time: 472.75 milliseconds (76.5%)
rebase/binding time: 27.01 milliseconds (4.3%)
ObjC setup time: 28.90 milliseconds (4.6%)
initializer time: 88.76 milliseconds (14.3%)
slowest intializers :
libSystem.B.dylib : 8.81 milliseconds (1.4%)
libMainThreadChecker.dylib : 14.42 milliseconds (2.3%)
AFNetworking : 18.43 milliseconds (2.9%)
Realm : 20.98 milliseconds (3.3%)
CYKJBasicModule : 12.96 milliseconds (2.0%)
  1. 删除不需要的三方库

  2. +load -> +initialize

    注意有的功能需要写在 +load 方法。可以改为 +initialize 后,用断点看看是否被调用。

  3. 动态库 -> 静态库

    如果 Podfile 中使用 use_frameworks!,那么第三方库都是以动态库的方式添加到工程中,动态库在启动阶段由 dyld 加载,静态库是运行时加载,所以为了减少 dylib loading time,可以减少工程中的动态库。

内存

iOS微信内存监控

包体积

  1. 删除无用代码和资源文件
  2. 压缩资源文件
  3. 动态下发 zip 包
  4. 内置 zip 压缩包

    • 首次启动需要解压,会牺牲首次使用的启动速度

    32 位、64 位双架构问题

    • 将引擎 zip 包置于 app 动态库内来规避这个问题,因为 AppStore 会针对动态库自动实现分架构下发
    • 需要注意下载失败、解压失败的问题。

iOS 优化实例的更多相关文章

  1. MySQL优化实例

    这周就要从泰笛离职了,在公司内部的wiki上,根据公司实际的项目,写了一些mysql的优化方法,供小组里的小伙伴参考下,没想到大家的热情很高,还专门搞了个ppt讲解了一下. 举了三个大家很容易犯错的地 ...

  2. mysql 优化实例之索引创建

    mysql 优化实例之索引创建 优化前: pt-query-degist分析结果: # Query 23: 0.00 QPS, 0.00x concurrency, ID 0x78761E301CC7 ...

  3. mysql sql优化实例

    mysql sql优化实例 优化前: pt-query-degist分析结果: # Query 3: 0.00 QPS, 0.00x concurrency, ID 0xDC6E62FA021C85B ...

  4. (转载)Android项目实战(二十八):使用Zxing实现二维码及优化实例

    Android项目实战(二十八):使用Zxing实现二维码及优化实例 作者:听着music睡 字体:[增加 减小] 类型:转载 时间:2016-11-21我要评论 这篇文章主要介绍了Android项目 ...

  5. iOS优化内存方法推荐

    1. 用ARC管理内存 ARC(Automatic ReferenceCounting, 自动引用计数)和iOS5一起发布,它避免了最常见的也就是经常是由于我们忘记释放内存所造成的内存泄露.它自动为你 ...

  6. PNG与iOS优化选项

    从App Store下载到的每一枚App最初都是一只IPA文件(其实是zip格式,内含特定规则的文件夹组织方式).但当作zip解开之后会发现里面很多的PNG文件看不了,这是因为在这些PNG图像都已被i ...

  7. mysql sql优化实例1(force index使用)

    今天和运维同学一块查找mysql慢查询日志,发现了如下一条sql: SELECT sum(`android` + ios) total,pictureid,title,add_time FROM `j ...

  8. iOS 优化方案浅析

    本文转载至 http://mobile.51cto.com/iphone-413256.htm Windows独特的注册表机制以及复杂的进程.内存管理,给了很多PC“优化”类软件极大的机遇,比如奇虎3 ...

  9. Android ListView性能优化实例讲解

    前言: 对于ListView,大家绝对都不会陌生,只要是做过Android开发的人,哪有不用ListView的呢? 只要是用过ListView的人,哪有不关心对它性能优化的呢? 关于如何对ListVi ...

随机推荐

  1. Docker 安装 Nginx 负载均衡配置

    Docker 安装 # 1)安装依赖包 yum install -y yum-utils device-mapper-persistent-data lvm2 # 2)添加Docker软件包源(否则d ...

  2. python随用随学-元类

    python中的一切都是对象 按着我的逻辑走: 首先接受一个公理,「python中的一切都是对象」.不要问为什么,吉大爷(Guido van Rossum,python之父)人当初就是这么设计的,不服 ...

  3. 石油测井专题(六)MCM工艺在LWD的应用

    在上一篇的MCM工艺我们提到过石英挠性加速度计的伺服电路采用此工艺可以有效提高仪器产品的稳定性和寿命. MCM相对于印制电路板(PCB)来讲,MCM技术采用了更短的连接长度和更紧密的器件布局,从而降低 ...

  4. 002-DOM事件实例-实现一个可以拖拽的登陆窗口

    前言:这是跟着慕课网一个老师的视频做的,这几天在重新的梳理自己,写完这个例子要系统的学一下jQuery,我司现在用的还是比较多,毕竟用了它不用考虑IE兼容性,可以让开发更有效率. 1.项目需求及基本的 ...

  5. 由一个项目需求引发的 - textarea中的换行和空格

    当我们使用 textarea 在前台编辑文字,并用 js 提交到后台的时候,空格和换行是我们最需要考虑的问题.在textarea 里面,空格和换行会被保存为/s和/n,如果我们前台输入和前台显示的文字 ...

  6. 关于毕业五年PHP成长疑惑

    1.PHP语法基础是否都会,比如异常捕捉,面向对象,数组操作语法,字符串操作,cookie,session,全局变量,超全局数组,防止sql注入,mysql预处理 2.MYSQL基础语法,字段设计,原 ...

  7. 网络流媒体协议的联系与区别(RTP RTCP RTSP RTMP HLS)

    目录 网络流媒体协议的联系与区别(RTP RTCP RTSP RTMP HLS) 简结 RTP RTCP RTSP 区别与联系 RTSP.RTMP.HLS 区别与联系 关于直播 流媒体各协议层次图 基 ...

  8. JavaScript(js)函数声明与函数表达式的区别

    在JavaScript中,函数是经常用到的,在实际开发的时候,我想很多人都没有太在意函数的声明与函数表达式的区别,但是呢,这种细节的东西对于学好js是非常重要的. 函数声明与函数表达式用代码写出来是这 ...

  9. 五分钟用Docker快速搭建Go开发环境

    挺早以前在我写过一篇用 `Docker`搭建LNMP开发环境的文章:[用Docker搭建Laravel开发环境](http://mp.weixin.qq.com/s?__biz=MzUzNTY5MzU ...

  10. 《ASP.NET Core 3框架揭秘》5折预售[发布试读章节]

    <ASP.NET Core 3框架揭秘>于昨天在下午京东正式开始预售,并在半天之内销售近一千套.为了回馈读者,出版社与京东谈了一个5折的价格,这是一个连我都没有想到的价格,至少我写着几本书 ...