对iOS安装包瘦身是很多App都必须要做的事,一般首先会对资源文件下手,压缩图片/音频,去除不必要的资源。这些资源优化做完后,我们还可以尝试对可执行文件进行瘦身,项目越大,可执行文件占用的体积越大,又因为AppStore会对可执行文件加密,导致可执行文件的压缩率低,压缩后可执行文件占整个APP安装包的体积比例大约有80%~90%,优化还是有意义的。
分析ipa文件:iOS可执行文件的组成
通过生成LinkMap文件,分析源代码生成的编译文件的大小。在Build Settings中Write Link Map File设置为Yes (记住release时候不要设置为Yes)。
编译之后会在build目录中生成两个LinkMap文件: XXX-LinkMap-normal-i386和XXX-LinkMap-normal-x86_64,分别代表在模拟器中32位和64位指令集生成的LinkMap文件。
LinkMap的文件详细结构解释
LinkMap会包含每个可执行文件的偏移量及大小,所以可以很方便的知道每个可执行文件的大小。
编译目录文件:~/Library/Developer/Xcode/DerivedData/XXX-eumsvrzbvgfofvbfsoqokmjprvuh/Build/Intermediates/XXX.build/Debug-iphoneos/XXX.build/
LinkMap分析工具
App瘦身checkList
编译选项
1.编译器优化级别
- Optimization Level 使用Fastest, Smalllest
该选项对安装包大小影响几无,但可以提高app的性能。参考wwdc 2013-Session408 Optimize Your Code Using LLVM - Strip Linked Product 设置为YES
需要注意的是Strip Linked Product也受到Deployment Postprocessing设置选项的影响。
在Build Settings中,我们可以看到, Strip Linked Product是在Deployment这栏中的,而Deployment Postprocessing相当于是Deployment的总开关。记得把Deployment Postprocessing也设置为YES, 该选项对安装包大小的影响非常大。
PS:Deployment Postprocessing这个配置项如果使用xcode打包,xcode会默认把这个变量置为YES, 如果使用脚本打包,记得设置。 - Symbols Hidden by Default设置为YES
- Make Strings Read-Only 设置为YES
-
Bitcode
设置为YES( ps:注意项目中的静态库,三方库等是否支持,有一个不支持就用不了,推不动别人改~~~)
关于bitcode, 知道这些就够了
iOS framework如何支持bitcode以及bitcode检测
资源瘦身:
1.清理无用图片
2.清理重复图片
3.无损压缩图片
代码瘦身
- 已经下线的陈旧代码,AB试验已经下线的代码
- 通过转H5、Hybrid或者RN实现的Native功能,可以定期清理
- 一些非核心Hybrid或者RN模块,可以考虑不要打包进入APP,通过动态下发的方式获取
- 代码的重构,UI组件、业务逻辑的重用等等
- 冗余字符串
代码上定义的所有静态字符串都会记录在在可执行文件的__cstring段,如果项目里Log非常多,这个空间占用也是可观的,也有几百K的大小,可以考虑清理所有冗余的字符串。另外如果有特别长的字符串,建议抽离保存成静态文件,因为AppStore对可执行文件加密导致压缩率低,特别长的字符串抽离成静态资源文件后压缩率会比在可执行文件里高很多。
资源瘦身
1、删除无用的图片文件
LSUnusedResources查找无用的图片文件
2、重复的图片文件
重复资源(主要指图片)不是指命名重复而是内容相同。
Duplicate Photo Finder(App Store有免费下载)
fdupes 是Linux下的一个工具,可以在指定的目录及子目录中查找重复的文件。
fdupes通过对比文件的MD5签名,以及逐字节比较文件来识别重复内容。
项目中图片目录,如 Assets.xcassets
和images
文件夹,所以:
brew install fdupes
fdupes -r xxx/images xxx/Images.xcassets
3、无损压缩图片
ImageOptim进行png文件的无损压缩
注意:
实际生产的安装包体积没有变小,因为COMPRESS_PNG_FILES
和STRIP_PNG_TEXT
设置成了YES,Xcode会重新压缩一次图片,但是压缩之后的图反而比ImageOptim处理之后的图更大。改成NO就能让项目中的PNG保持不变。如果搜不到,手动添加一下。
4、WebP图片压缩
WebP是Google提供的一种图片编码格式,通常情况下WebP格式的图片是原始JPG/PNG图片的1/3,所以对于重度依赖图片显示的应用,转换使用WebP可以节省大量的网络传输数据和时间。对于APP瘦身,使用WebP格式可能是一种方式,可以使用WebP格式的图片替代现有的图片资源,可以一定程度的节省空间。
注:iOS原生并不支持WebP格式加载,需要引入SDWebImage/WebP
Webp劣势:(慎用)
- 压缩时间长,大概是png的8倍左右(不过一般都是在服务端压缩,客户端解码,所以服务端可以做个预压缩)
- 解码时间比png长,大概几十毫秒。WebP是节省了流量(图片小),增加了解码时间,换句话说就是:同样的图片,网络越快(图片更小的WebP就没有明显优势),图片越多(WebP要解码),WebP比png要慢。
- UIWebView,WKWebView都不支持WebP。(UIWebView可以用NSUrlProtocol来解决,但是WKWebView还没有太完美的办法,谁知道的请告诉我下)
- 不支持流式解压缩(即图片加载的时候会由模糊慢慢变清晰的过程,WebP貌似不支持这种解压缩方式)
5、AppThinning
方式一:安装npm包(需要查看文档,安装node环境)
npm i appthinning -g
方式二:克隆源码,直接参考文档
使用:
appthinning -d "/Users/catchzeng/Desktop/test" -t "png|jpg" -s 1000 -m 2000 -c imageOptim
6、AssetCatalogTinkerer
AssetCatalogTinkerer 是一款开源的查看和提取 car 文件中的图片工具。
导出所有图片后,就可以根据大小排序找到大文件,进行对应的压缩处理。
代码瘦身
1、AppCode代码静态检查
AppCode提供了非常强大的代码静态检查工具
1.Inspect Code:检查代码
2.Code Cleanup:代码清除
3.Silent Code Cleanup:无声代码清理
4.Run Inspection by Name:自动检查清除冗余资源
5.Configure Current File Analysis:配置当前文件分析
6.View Offline Inspection Results:查看离线检查结果
7.Infer Nullity:推断出无效
8.Locate Duplicates:查找重复
9.Show Coverage Data:显示覆盖数据
10.Analyze Dependencies :分析依赖性
11.Analyze Backward Dependencies :分析落后的依赖关系
12.Analyze Module Dependencies:分析模块依赖关系
13.Analyze Dependency Matrix:分析从属矩阵关系
14.Analyze Cyclic Dependencies:分析循环依赖关系
15.Analyze Data Flow to Here :分析到这里的数据流
16.Analyze Data Flow from Here :从这里分析数据流
17.Analyze Stack Trace :分析堆栈追踪
自动检查清除冗余资源详细功能Name对应Idea中Preferences—>Editors—>Inspections中所有内容
1、清理无效类 Run Inspection by Name:Empty Class
2、查看未使用方法 Run Inspection by Name:Unused declaration
包含了项目里面声明了没用使用过的变量
,方法
和类
对于检测的内容,idea提供四种解决方案
3、查看类中有未使用引用 Run Inspection by Name:Unused import
可以参考AppCode inspections for your code perfection
2、清除无用代码
01. AppCode搜索出来的无用的Class,会有误报需要仔细检查每一个报错的代码。
02. 使用Fui查找发现无用文件,可以用于查找无用的import,同时也提供xcfui 可以和Xcode集成。
清除无用类
fui find
fui --path=~/source/project/Name --ignore-path=Pods --ignore-path=Libraries find
- 清除无用的Import
fui -g --path=~/source/project/Name --ignore-path=Pods find
fui -l --path=~/source/project/Name --ignore-path=Pods find
03. SMCheckProject使用
由于clang插件检索出的无用方法没法确定能够直接删除,还需要挨个检索人工判断是否可以删除,这样每次要清理是需要人工排查一遍是非常耗时耗力的。这里推荐一个使用Swift3写的MacOS程序,这个工具可以很方便快捷的找出工程项目下未被调用的方法可以检测出objc项目中无用的方法,支持一键清理。
注意点:
01:编译工程:作者的swift版本是3.0 2020.12.12 swift需要支持5.0
02:项目中路径fix
03:语法错误,根据提示fix一下
04: 工程路径需要写对,不然找不到具体的类。
05: 一键清理的时候语法报错:改成 URL(fileURLWithPath:mFilePath)
06:清理的方法有可能是子类继承,category,base类,potocol,有的拼接的方法。需要自己再仔细确认一下。
(瘦身收益不大,还容易出问题,谨慎删除)
04 . 查找相似的代码:SameCodeFinder可以查找到相似的代码,最后一位数字代表两个文件的海明距离,数字越小说明两个文件越类似。
清除无用的Method
xib/stroyboard替换
无用三方库删除
-
静态库瘦身
暂时还没选择,可以参考文章iOS APP安装包瘦身实践
项目中多少都会引入一些第三方静态库,通过lipo
工具可以查看支持的指令集,比如:
lipo -info libWeChatSDK.a
i386,x86_64,这不是模拟器的指令集么?去掉看能不能减少体积?armv7可以兼容armv7s,armv7s也可以删了,只保留armv7和arm64lipo libWeChatSDK.a -thin armv7 -output libWeChatSDK-armv7.a lipo libWeChatSDK.a -thin arm64 -output libWeChatSDK-arm64.a lipo create libWeChatSDK-armv7.a libWeChatSDK-arm64.a -output libWeChatSDK-device.a ls -ll -rw-r--r-- 1 Vic staff 5957080 Jan 6 14:40 libWeChatSDK-device.a -rw-r--r-- 1 Vic staff 14410376 Nov 25 11:53 libWeChatSDK.a
ipa优化了5M左右。大部分是图片资源,和无用的文件。
参考文章
iOS可执行文件瘦身
iOS APP瘦身实践,资源优化、编译器配置优化、可执行文件优化
滴滴出行iOS端瘦身实践, 提供了查找无用图片的工具、WebP图片压缩、基于clang plugin实现查找无用代码、查找类似代码
基于clang插件的一种iOS包大小瘦身方案
检测出objc项目中无用方法,然后一键全部清理
lipo command(Mac)
iOS APP分析无用代码
iOS 安装包瘦身 (上篇)
iOS 安装包瘦身(下篇)
AppCode使用技巧(一)——Inspections
AppCode使用技巧(二)——Completion
AppCode使用技巧(三)——实时模板
AppCode使用技巧(四)——搜索和导航
优化安装包大小
iOS APP应用包瘦身综合实践小结
工具篇——idea的清理无效代码
今日头条优化实践: iOS 包大小二进制优化,一行代码减少 60 MB 下载大小