iOS-性能优化的那些事

柯里露台
• 阅读 2894

前言
本人在这家公司已经三年多了,这款三年多我一直在做的APP也烂熟于心,APP也0到1到目前的500万的用户量;对于APP的功能来说也是比较全面的,用到的技术知识点也比较多吧,APP的优化也是一直在做的事情,而且APP性能的优化也不是一朝一夕的事情,在此离别之际,我将详细说明讲解一下我在三年里对APP性能优化方面做过的一些事,大家仁者见仁智者见智,也欢迎大家进群提供宝贵的意见和建议!

基础优化
使用ARC,现在的iOS开发大家用的都是ARC,几乎没有人再去使用MRC了,使用ARC的好处就是不用再时时刻刻注意要释放创建的对象了;避免使用xib或者storyboard。

这里说一下xib和sb的缺点吧,如下:

1.占用API包比较大;
2.导致APP启动时间比较耗时,因为在APP启动main()以前需要加载他们;
3.加载速度比较慢;
4.后期的版本更新迭代维护时间成本比较高;
5.多人开发容易引起冲突。

列表图片优化
列表不论在哪一个APP中是使用最为广泛的一款控件了,在我的APP中也不例外,我们的APP只要功能列表类似于微信的朋友圈,图片有0~9张的形式还可以是视频文件;
先说一说图片吧,如果一个列表都是9张图片,列表在加载和滑动的时候会耗用过多的内存;我在这里是把图片这一块单独抽出来做一个图片资源的封装,然后根据创建的图片容器(UIImageView)的大小加载缩略图,我们公司的APP存储用的是七牛云存储,所以在获取图片资源的时候,只需要设置对应的字段就可以拿到缩略图了,点击的查看大图的时候才查看原图;

再说说视频,视频的处理逻辑和图片差不多,这里在CELL上我们使用一个UIImageView来替代视频播放器,可以去出视频的第一帧作为封面,点击图片的时候才调用我们封装好的视频播放组件。

复用机制
说道复用,我们可能常用的有CELL的复用,其实我们也可以自己写我们的服用,就比如上图中的列表,我们一般采用的思路就是在主控制器上添加一个UIScrollView,再根据有多少个小标题类型创建多少个子控制器,接着把子控制器添加到主控制器的childViewControllers中,最后把子控制器的视图添加到UIScrollView上,有没有更节省内存空间的做法呢???
当然有的,我们可以只创建5个控制器然后丢到我们的可重用数组中,根据每次滑动去加载不同的缓存数据;
还比如我在直播间创建刷礼物的视图动画的时候,因为最多只能显示三条,那么我只会创建三个视图,当有大于三条的礼物信息过来的时候也只会创建三个视图,然后丢进我的可重用数组里面,每个视图动画完成以后才重新复制Model,如下图左下角的礼物动画最多三个,最少没有:

就如上面所说,在项目中我们可以在很多地方创建属于我们自己的重用机制!

离屏渲染
在开发中,我们常用有圆角处理、阴影、遮罩等等;先说说圆角优化吧,我们一般设置圆角的方式如下:

view.layer.cornerRadius = 10;
view.layer.masksToBounds = YES;
这样处理的渲染机制是GPU在当前屏幕缓冲区外新开辟一个渲染缓冲区进行工作,也就是离屏渲染,这会给我们带来额外的性能损耗,如果这样的圆角操作达到一定数量,会触发缓冲区的频繁合并和上下文的的频繁切换,性能的代价会宏观地表现在用户体验上——掉帧。

优化方案:
a.可以做一个透明的png图片盖在上面;
b.使用贝塞尔曲线UIBezierPath和Core Graphics框架画出一个圆角;
c.使用CAShapeLayer和UIBezierPath设置圆角;
d.也可以将图片的处理放在服务端(比如:七牛云储存就可以设置图片的圆角);
e.尽量把view设置成不透明的。

说明:离屏渲染还可以做很多东西,具体的可以自行查找!

懒加载
这里的懒加载主要说的是懒加载思想,可以懒加载的类型有很多,当然好处有很多,最主要的是可以节省内存资源;

重大开销对象
我们在APP使用过程中会用到很多重大开销对象(比如NSDateFormatter和 NSCalendar),如我们在列表需要计算用户年龄的时候会经常用到NSDateFormatter,还有一些时间的格式化输出,或者在网络请求的时候需要传一些时间戳,所以我们可以把NSDateFormatter放在单利里面,这样就不用经常创建了,其他的也是同样的道理。

还有就是,像年龄生日什么的最好不要由前端APP来计算,最好放在服务器上,由服务端计算好然后再传给我们。

内存警告
如果程序在运行过程中发生了内存警告(didReceiveMemoryWarning),我们需要快速应急处理一下,不要用不了多久APP就会被杀死掉,所在在收到内存警告主要思路就是想着去清理栈上的东西,以后我们可以做以下几点:

a.清理不需要的已经创建的对象,不论是试图还是工具类;

b.释放单利里面不需要的对象,比如上文提高过得重大开销对象;

c.如果有正在下载的任务,取消或者暂停全部任务;

d.如果使用了SDWebImage,可以清理一下缓存clearMemory;

主线程流畅
不要阻塞主线程,要保证主线程的流程性;我们不要把一些重大开销对象放到主线程里面,我们可以创建子线程去处理这些事情;比如多个网络请求结束一起刷新UI、多个动画效果、数据的读写操作等等;

数据缓存
做缓存这个事情,一方面减小内存的小号,还有很重要的一方面就是优化用户体验;可以做缓存的东西很多,我们可以对数据接口进行缓存,还可以对WebView进行缓存,还有图片缓存、高度缓存等等;

在这里不得不说一下,数据存储了;我们在做缓存的时候选择正确合适的存储方式也很难重要,当然大家也可以根据项目的实际需求来选择存储,我们公司的APP本地存储我选择的是SQLite,管理类是我基于FMDB的又一次封装.

网络API优化
这个优化不单单需是前端小伙伴的事,还需要后端开发人员的配合,避免一些不必要数据的返回,更要避免在APP端处理或者计算太多东西,比如年龄、星座的计算;即使后端的小伙伴把一些不必要的数据返回了,我们在创建数据模型Model的时候可以选择不去接收!

PS:这里我需要吐槽一下,以前公司有个java后端,返回的数据全部是一个表的实体类,管你有用没用,直接一股脑的全给你,自己去计算和自己去查找,那真叫一个心累啊,所以一个优秀的API开发工程师也是一个非常重要的原因!

自动释放池
自动释放池(autoreleasepool)在MRC的时代真是用的非常多,但是现在的项目都是ARC,自动释放池用的也就比较少了,因为有系统帮我们监管,但是如果我们一个页面创建了太多的类或者对象,如果等页面销毁的时候由系统统一释放难免会出现一个峰值影响整体性能,这时候我们就可以考虑使用autoreleasepool了,避免峰值的出现!?

还比如我们在遍历一些大数组或者字典的时候,可以使用自动释放池来降低内存峰值,比如:

NSArray *bigArray = @[] //这是一个很大很大的数组
NSMutableArray *newArray = [[NSMutableArray alloc] init];
for (NSStirng *item in bigArray) {
    @autoreleasepool {

    ZFJModel *model = [[ZFJModel alloc] init];
    model.item = item;

        [newArray addObject: model];
    }
}
APP启动优化
在AppDelegate里面我们会写一些很多东西,你写的东西越多越影响APP的冷启动时间就会越长,因此我们需要对AppDelegate进行减负,具体如何减负大家可以根据各自项目的实际情况,第一可以删除一些不是必须的东西;第二可以把一些东西写在别的地方(如RootViewController),我在APP的RootViewController写的东西比如IM聊天的配置初始化登录,一些未处理的任务,还有一些版本的坚持和缓存的清理等等!

Instruments
Instruments 是什么我这里就不作过多的介绍了,这里我主要说我用Instruments干什么;我平时用Instruments主要干两件事,一件事是检查内存泄漏,还有一件事是检查耗时函数;对于内存泄漏我们对应修改补漏就行了,对于耗时函数要么就换一种写法,要么就创建一个子线程来处理!

?这里要说一个我的习惯,我的所有的控制器都继承于BaseViewController,然后我再BaseViewController里面写了以下的一部分代码:

  • (void)dealloc{
    NSLog(@"=== %@ dealloced! ===", NSStringFromClass([self class]));

}
如果我的页面销毁不走dealloc的打印,那么页面肯定有没有被释放的对象,要么是发生循环引用了,要么是需要手动释放,具体打印以下对象的引用计数!

iOS-性能优化的那些事

本文本人首发www.zfjobslib.com。 【iOS代码混淆工具】版本:ZFJObsLib 1.7.2
点赞
收藏
评论区
推荐文章
待兔 待兔
4年前
go, iris , nuxt, 服务端渲染等技术在helloworld开发者社区中的应用与实践
大家好,helloworld.net上线已经有近半年的时间了,转眼过的好快,在这半年的时间里,迭代了近10多个版本,优化了很多的体验,交互上的不足之处,同时也上线了我们的安卓app,苹果的因为还在申请开发者账号,所以暂时未上线在这半年的时间内,网友很给力,也给出了很多的建议和优化,也有不少网友说愿意为helloworld开发者社区出一份力,在这里我感
Python进阶者 Python进阶者
3年前
手把手教你进行安卓逆向之篡改apk名称和图标
前言Hey,大家好呀,我是码农,星期八!最近假装是时间多了吧,打算学习安卓逆向相关的。先小试牛刀了一下,如何篡改app的名称和图标,一起来了解一下吧!环境app土豆.apk逆向工具AndroidKillerv1.3.1篡改app名先看一下我们正常的app打开工具AndroidKiller,将土豆.apk拖拽进去,时间会比较长...不进行工程分析
Karen110 Karen110
4年前
有读者问我怎么爬App,我手把手教了他(多图警告)
前言大家好,我是Kuls。最近看见很多读者在说怎么抓取APP上的内容为此,我打算写一些关于爬取APP方面的文章,当然APP的爬取自然是要比网页要麻烦。但是只要我们把前期的工作做好,后面也会更加的顺利。今天这篇文章就是来教大家如何抓取到APP数据,用什么软件,怎么配置?Charles首先,我们来看看百度百科是怎么介绍这款软件的是一个HTTP代理服务器,HTT
Wesley13 Wesley13
4年前
APP安装体验至关重要,个性化安装势在必行!
对普通用户来说,他们能直接感知到的只是一个App的用户体验好不好,操作麻不麻烦。用户的这些感受直接决定他们是否弃用一个App。App的安装体验其实就是App给人的第一印象,APP个性化安装就是顺应时代的产物,为了满足每个用户对APP的不同需求而采取的技术。能够根据用户的安装来源,为用户精确定制相应的个性化内容;也能简化用户操作步骤、优化用户体验,直达App的
Stella981 Stella981
4年前
Android 客户端性能优化
众所周知,一个好的产品,除了功能强大,好的性能也必不可少。有调查显示,近90%的受访者会因为APP性能差而卸载,性能也是造成APP用户沮丧的头号原因。那Android客户端性能的指标都有哪些?如何发现和定位客户端的性能问题?本文结合多个项目的开发实践,给出了要关注的重要指标项目,以及定位和解决性能问题的一般步骤。性能优化应该贯穿于功能开发的全部周期,
京喜APP - 图片库优化 | 京东云技术团队
京喜APP早期开发主要是快速原生化迭代替代原有H5,提高用户体验,在这期间也积累了不少性能问题。之后我们开始进行一些性能优化相关的工作,本文主要是介绍京喜图片库相关优化策略以及关于图片相关的一些关联知识。
Flutter热更新技术探索 | 京东云技术团队
APP发布到市场后,难免会遇到严重的BUG阻碍用户使用,因此有在不发布新版本APP的情况下使用热更新技术立即修复BUG需求。原生APP(例如:Android&IOS)的热更新需求已经比较成熟,但Flutter技术栈目前还缺少类似的技术方案,因此Flutter研发团队,也需要类似的热更新技术。
从iOS App启动速度看如何为基础性能保驾护航 | 京东物流技术团队
启动是App给用户的第一印象,一款App的启动速度,不单单是用户体验的事情,往往还决定了它能否获取更多的用户。所以到了一定阶段App的启动优化是必须要做的事情。
鸿蒙小林 鸿蒙小林
7个月前
《仿盒马》app开发技术分享-- 逻辑优化第三弹(83)
技术栈Appgalleryconnect开发准备现在我们的app功能已经趋近完善,bug和缺失的细节也越来越少了,我们继续对app进行优化,首先是我们的积分页面,我们只实现了全部的积分展示内容,对收入和支出的积分明细并没有进行展示,这里我们要实现一下,然后