iOS包瘦身

iOS包瘦身我的思路在于以下几点:

  • 资源文件优化:资源文件包括图片、gif、音频、文本、配置文件、xib、storyboard等。
  • 对.o(可执行)文件优化:.o文件由我们编写的代码.h和.m(源文件)编译后生成。
  • 设置Xcode的编译选项优化:通过设置Build Settings进行优化。

1.资源文件优化

  • 删除无用的资源文件;
  • 对资源文件进行压缩;
  • 变更图片文件的导入方式;
  • 资源的必要性

1.1删除没有用到的资源

之前某些版本里面改了UI或者某些页面不用了,导致有一些图片一直遗留下来忘记删掉,可以使用工具LSUnusedResources去查找项目中的多余资源。关于使用的方法链接里也有详细的介绍,这里就不赘述了。(这里有一些坑,扫描出来的无用图片有可能被使用了,但脚本不能识别,例如某些图片的名字是由后台传过来的,这样识别不了。)

1.2对资源文件进行压缩

对于资源文件进行压缩的话要和相关同事做好沟通,例如图片不能压缩得太过模糊导致ui根本不收货。

图片压缩工具有很多,这里介绍两个好用的:

  • 无损压缩工具ImageOptiom(推荐)。这是一款非常好的图片压缩工具,可以进行无损压缩,能够对 png 和 jpeg 图片文件进行优化,它能找到最佳的压缩参数(在设置中可以设置压缩比例,80% 及以上是无损压缩,推荐使用),并通过消除不必要的信息(如文件的 EXIF 标签和颜色配置文件等),优化后达到减小文件大小的效果。
  • 有损压缩工具TinyPNG。它使用聪明的有损压缩技术,能有效减少PNG文件的大小。通过选择性地降低图像中颜色的数量,需要更少的字节来存储数据。

【建议】:对于较大尺寸的图片,可以和设计沟通,在不失真和影响效果的前提下,使用TinyPNG进行压缩;较小尺寸的图片,建议使用ImageOptiom。

进行图片压缩的时候项目使用.xcassets管理,而且图片文件结构是这样的,如果我要一个一个更换图片的话估计会崩溃。

iOS包瘦身_第1张图片

所以得使用批量压缩更换图片的脚本,可以参考这篇文章。

修改完脚本里面的参数后,控制台cd到脚本目录,python tinyPng.py运行脚本,然后等待图片复制(数量大的话挺久的)。

1.3变更图片文件的导入方式

图片资源的导入方式有如下几种:

1. Assets.xcassets。

    • 只支持png格式的图片;
    • 图片只支持[UIImage imageNamed]的方式实例化,但是不能从Bundle中加载;
    • 在编译时,Images.xcassets中的所有文件会被打包为Assets.car的文件。

2. CreateGroup

    • 黄色文件夹图标;Xcode中分文件夹,Bundle中都在同一个文件夹下,因此,不能出现文件重名的情况;
    • 可以直接使用[NSBundle mainBundle]作为资源路径,效率高;
    • 可以使用[UIImage imageNamed:]加载图像。

3. CreateFolderRefences

    • 蓝色文件夹;Xcode中分文件夹,Bundle中同样分文件夹,因此,可以出现文件重名的情况;
    • 需要在[NSBundle mainBundle]的基础上拼接实际的路径,效率较差;
    • 不能使用[UIImage imageNamed:]加载图像。

【说明】:蓝色文件夹只是将文件单纯的创建了引用,这些文件不会被编译,所以在使用的时候需要加入其路径。

4. Bundle(包)

对于上面这几种不同的导入方式,会对打出的包的大小有影响么?

经过测试得知:CreateGroup、CreateFolderRefences两种方式打出来的包,图片都会直接放在.app文件中,所以打包前后,图片的大小不会改变。而加入到Assets.xcassets中的方法则不同,打包后,在.app中会生成Assets.car文件来存储Assets.xcassets中的图片,并且文件大小也大大降低。

1.4资源的必要性

对于某一些资源来说是不是必须要导入到工程中?或者说,有没有别的办法替代。

  1. 一些图片、音频、视频可以做成下载的形式,如游戏中到达某个关卡才下载对应的资源。
  2. 比较简单的图片、动态图使用代码去实现。关于动态图和一些动画这里安利一个第三方:Lottie了解一下,生成JSON文件去做一些动画(iOS 、android、RN都支持),可以干掉项目中的gif图。
  3. 可以把xib、storyboard干掉,用纯代码的形式去实现。
  4. 一些比较静态的页面,例如纯展示的页面,能不能通过协商丢到webview去做呢?

对于资源的必要性这只是其中几点,肯定还有很多办法继续优化。

2.对.o(可执行)文件优化

.o是我们写的xxx.m、xxx.h经过编译后的可执行文件,每一个.o文件的大小可以通过linkmap文件计算出来。

首先我们设置xcode的Write Link Map File选项。XCode -> Project -> Build Settings -> 搜map -> 把Write Link Map File选项设为yes,并指定好linkMap的存储位置。默认地址是在~/Library/Developer/Xcode/DerivedData/xxx-xxx-fwtuexpkzxsfkjaootcqwizogrhf/Build/Intermediates/xx-xxx.build/Debug-iphonesimulator/xxx-xxx.build/xxx-xxx-LinkMap-normal-x86_64.txt(文件路径顺序基本一致,文件名会有所不同,自行查看)。

拿到linkmap后可以通过一些脚本工具去进行分析,我用的是这个小工具。分析过后可以看到类似的界面,这样就可以看到各个文件的大小了。

iOS包瘦身_第2张图片

对于可执行文件的优化其实就是优化我们所写的代码,分为一下几点:

  • 删除没用的代码。
  • 提高代码的复用性。
  • 用更少的代码实现功能。
  • 删除第三方或者精简第三方库。

2.1删除没用的代码

项目经过不断的迭代,有一些类,一些代码已经不会被使用到了,找出它们并删除掉。这里也提供一个工具,可以用来找无用的类。

2.2提高代码的复用性

对一些常用控件进行封装(共用弹窗等),可以复用的代码块做成工具类减少复制黏贴的代码。使用一些基类,可以把一些重复的代码丢到基类里面。对于一些不怎么改动,而且在项目中也比较稳定的功能模块,可以选择打包成静态库的形式。这样既可以提高复用,又可以减少编译时间。以上只是很少的一部分,办法还有很多。

2.3用更少的代码实现功能

这个没什么好说的,试着重构代码吧。

2.4删除第三方或者精简第三方库

把一些重复功能的第三方库删除掉,或者只用到很少功能的第三方去掉,自己用原生代码实现。某些第三方库我们只用到部分功能,可以对他作出精简,例如有些IM第三方会提供UI模块,而这个我们完全可以自己写。

对于代码的优化,感觉优化效率比较低,对于包size的减少没有很明显的改变,远没有优化资源来得爽利,而且优化代码需要很熟悉相关的业务,不然改着改着出现一堆bug。这也是考验重构能力的地方,要做的东西有很多,效果也不明显,但是不能放弃治疗。

3.编译优化

关于编译优化这一块,说起来是一个很大的东西,而且我也是只看了些皮毛。想要做好编译优化这一块,感觉需要学习的东西有非常多。所以只能简单说说我关于编译这一块的一些理解,有理解错误的地方欢迎指正。

想要对编译做出优化,那么我们就先要了解我们平时command+B的时候Xcode做了些什么。其实当我们按下command+B或者command+R的时候Xcode就会去执行一堆clang的命令,对我们的代码进行编译,也可以在Xcode中看到具体执行了什么命令,然后结果是怎样的(成功、错误、警告等等)。对于Xcode的编译我们也可以手动通过clang命令一步一步的去拆分,看看每一步生成的是什,具体可以跟着这篇文章去做。

说到clang,那就不可避免的要了解到LLVM。LLVM是什么?

LLVM是构架编译器(compiler)的框架系统,以C++编写而成,用于优化以任意程序语言编写的程序的编译时间(compile-time)、链接时间(link-time)、运行时间(run-time)以及空闲时间(idle-time),对开发者保持开放,并兼容已有脚本。

LLVM计划启动于2000年,最初由美国UIUC大学的Chris Lattner博士主持开展。2006年Chris Lattner加盟Apple Inc.并致力于LLVM在Apple开发体系中的应用。Apple也是LLVM计划的主要资助者。

目前LLVM已经被苹果IOS开发工具、Xilinx Vivado、Facebook、Google等各大公司采用。

引用百度一段对于LLVM的一段介绍,我们可以认为LLVM一个完整的编译器架构,也可以认为它是一个用于开发编译器、解释器相关的库。

LLVM分为前端和后端两个部分。其中前端部分接受不同的语言代码,如OC、C++等。对不同的语言进行词法、语法、语意分析等,然后生成中间代码(IR code),其中IR代码可以经过多个优化流程(Pass),对的这个叫Pass的东西就是我们想要的编译优化!通过编写不同的Pass可以对编译的时间、包大小进行优化。然而我并不会写......感觉这个东西有点高级,想要做这个还是有点困难的,苹果有做相关的优化,可以通过设置Xcode的BuildSettings选项来配置。Pass走完以后会来到后端,后端会根据IR代码生成符合各个CPU架构的ipa包。

关于编译相关的东西由于篇幅有限,就写了一些自己的理解,也不知道有没有错误。看了一些资料,也不能说百分百的理解。然后如果对这方面有兴趣的推荐下面一些博客,或者文章。都是我之前看的,看得也比较零散。

  • LLVM零基础学习
  • 深入理解程序编译过程
  • iOS编译过程的原理和应用

  • 关于Xcode编译性能优化的研究工作总结

上面最后一篇文章有详细介绍如何配置Xcode的BuildSettings选项,也对各个选项做了相关的解析。

你可能感兴趣的:(iOS开发)