iOS 瘦身必知必会

105 阅读3分钟

image.png

Mach-O 文件构成:

  1. Header 头部:指明了 CPU 架构,文件类型,LoadCommand 的个数,用来校验 Mach-O 合法性和定位文件的运行环境
  2. LoadCommand 加载命令:告诉 OS 如何加载和链接段数据 segment
  3. Data 数据段:存放 __DATA(数据段) 和 __Text(代码段) 段的数据,真正存储 App 二进制数据的地方,

如何检测无用代码?

  1. 静态检测:用 otool 工具分析 Mach-O 文件,针对 classlist 段(所有的OC 类和 Swift 类)和 classrefs (所有引用类)做差集,就能找到未使用的类。除了这两个主要的,还有一些其他情况,比如:

    • 通过字符串调用的类、__DATA__cfstring
    • 没有直接调用这个类,但是这个类的 +load 调用了 检测 __DATA __objc_nlclslist 段()
  2. 动态检测:通过检测 OC 类的元数据中某一个标记位 RW_INITIALIZED ,就能找出所有使用到的类,再跟类的全集做差集,就能得到未使用的类了。参考WWDC:Advancements in the Objective-C runtime

如何配置编译选项

  1. 符号剥离(链接期的优化):官方文档

    App 本身可以看做是一个大的「动态库」,既然是「动态库」那么就会有向外暴露的符号(也就是 Exported Symbols),这些符号实际上是没有用的。可以想办法删掉。(方法是在项目的 Build setting 中,设置 EXPORTED_SYMBOLS_FILE 为一个路径,路径指向一个 txt 文件,在 txt 文件里写了哪个符号,那么这个符号就会被保留,其他符号就会被裁剪掉)

  2. GCC 编译优化: GCC_OPTIMIZATION_LEVEL

    更激进的 GCC 编译优化—— Oz 模式,原理是通过更多的外联来降低函数的内联层级,但是同时函数的调用栈就会变深,等于是用时间增加换了空间减少,函数的执行效率被降低。

如何处理资源文件?

  1. 用 python 脚本扫描出扫描出项目中所有用到的图片,用 LSUnusedResources 扫描出所有项目内未使用的图片资源,做一个去重,剩下的就是实际上未使用的图片。删除无用图片。

  2. 有损压缩,将所有图片资源都做一次有损压缩。tinypng

  3. 用 AssetCatelog 管理。

    • 有两个好处,一个是 app thinning,Apple 会把不同分辨率的 资源包下发给不同的设备,所以整体的 IPA 包虽然变大了,但是实际下载的安装大小是变小的
    • Xcode 会对 AssetCatelog 里的图片做一个无损压缩,然后把多张图合并成一张大图,读取的时候只能通过 Apple 的 API,它通过坐标等方式,从合成后的大图中获取对应的图片。这种方式对小图有更好的效果。

如何防劣化?

  1. 每次打包后触发包检测脚本,生成当前包的体积分析报告,让其他开发者和产品有感知
  2. 定期代码检测,下线无用代码
  3. 合并代码时,如果有新增图片资源的,确保要先经过有损压缩

参考资料

如何让云音乐 iOS 包体积减少 87MB

WWDC:Advancements in the Objective-C runtime