本文字数:字
预计阅读时间:59分钟
背景包大小优化是项目开发中不可避免会遇到的,网上关于包大小优化的文章很多,每篇文章说的都不尽相同,笔者曾经根据网上的文章做过包大小优化,但效果不尽人意;因此笔者想根据已有的文章、知识结合自己的理解、实践,做一份总结梳理,整理自己的包大小优化逻辑,不光要知道怎么做可以让包大小变化,还要知道为什么这么做能产生效果,所以就有了这篇文章。
分析想要优化安装包大小,首先需要弄清楚影响安装包大小的因素有哪些?之前笔者优化包大小直接闷着头就去瘦身,瘦来瘦去也没瘦出个名堂,而且还跟别人说不清楚自己做了什么,为什么这么做?
后来总结出来,做事之前要先思考、分析、最后再去做,要思考的是影响这件事的因素有哪些,一一列举出来,查漏补缺;然后针对这些因素进行分析,分析哪些因素是人为可控的,哪些因素是不能改变的,针对可控的部分要怎么优化,不可控的部分是否能避免,最好可以使用思维导图工具,一一记录;然后按照思维导图的整理出来的数据,按步骤去执行。
回过头来,针对安装包大小,首先分析影响安装包大小的因素,有:Xcode的设置、资源、代码三个方面。那针对这几个方面要怎么优化?以及如何查看每一步优化的结果?
首先是怎么优化的问题:
Xcode的编译设置优化,Xcode设置影响的是生成包的大小,通过Xcode编译选项优化的设置,让生成的ipa包变小,比如不含断点调试、去掉异常支持等等。
资源文件的优化,资源不光有图片资源,也包含代码资源和其它导入的资源,可以通过分析安装包构成,看里面哪些部分比较大、不合理,从而进行优化。
代码的优化,通过LinkMap生成LinkMapFile,分析LinkMapFile各文件占用,结合Mach-O文件进行分析优化。
然后是怎么查看每一步优化的结果的问题:
查看每一步的优化结果,可以通过分析打包出来的ipa的大小,以及ipa的组成,与初始的ipa包大小比较,即可直观得到优化的结果。但可以更进一步,分析ipa的构成,对比优化后的构成,看每一步的操作具体影响的是包的哪一块儿,从而导致包的大小发生了变化。所以先来看一下一个ipa的包包含哪些内容,然后每一步优化之后,对应ipa的哪一部分发生了变化?
安装包的构成iOS打包出来的ipa,本质上是一个压缩包,所以可以将.ipa的后缀改为.zip,然后进行解压缩,之后会得到一个Payload文件夹,里面又一个xxx.app的文件,这个xxx.app就是包含所有文件的包了,选中xxx.app,右键显示包内容,即可看到里面具体包含的东西了,大致如下:
安装包:
_CodeSignature:ipa包签名文件.lproj:语言文件Frameworks:第三库、SwiftSupport库Plugins:App创建的扩展,比如:Widget、Push、分享Assets.car:由Assets.xcassets生成的资源文件,里面包含各种分辨率的图片embedded.mobileprovision:证书配置文件Info.plist:项目配置exec格式的xxx:可执行包其它资源文件.mp3格式的文件.html的文件.json的文件.png或者.jpg的文件示例如下,Ps:不得不说,笔者这个ipa包含的内容真的是很全面了,各种的资源都有,哈哈哈
笔者初始ipa包大小为22.9M,解压缩之后.app的大小为57.1M,其中各部分大小明细如下
内容大小_CodeSignature93KB.lproj4KBFrameworks37.5MBPluginsKBAssets.car4.9Membedded.mobileprovision8KBInfo.plist6KBexec格式的xxx13MB其它资源文件1.4MB了解了iPa包的组成之后,我们再回过头来,按照Xcode的编译优化、资源文件优化、代码优化的步骤来一步步分析。
Xcode编译设置一般这一步容易被人忽略,因为提到优化最先能想到的就是资源优化,比如图片压缩、无用代码删除等等,而对于Xcode自身的编译优化提及的反而不多。而且由于网上提供的参考针对每个项目可能结果都不一样,有些编译选项的设置是需要针与实际项目结合起来才可以,所以笔者这里整理和总结了一下:
Xcode编译优化相关:
BuildSettings中去掉异常支持,EnableC++Exceptions和EnableObjective-CExceptions设置为NO,OtherCFlags添加-fno-exceptions;
注意:EnableC++Excptions和EnableObjective-CExceptions是指项目支持对错误的异常处理,比如trycatch、throw之类的;所以如果项目中使用的有类似的异常处理的,这个关闭了之后会报错(Cannotuse
trywithObjective-Cexceptionsdisabled)。包括宏定义中使用的有try{}、finally{}之类的,比如strongify等,如果关闭了最后打包的时候也会报错。-fno-exceptions的意思是禁用异常机制,参考gcc,同样,当项目中有trythorw的时候,就不要设置这个选项为NO
?Beforedetailingthelibrarysupportfor-fno-exceptions,firstapassingnoteonthethingslostwhenthisflagisused:itwillbreakexceptionstryingtopassthroughcode