应用距离上次瘦身已接近一年时间,恰好版本修改了一些功能实现,需要删除一些三方库使用,所以借机进行一次应用瘦身。在此将本次使用和查询到的瘦身方法做一些总结。
ipa文件内容
IPA文件包主要包括可执行文件、签名文件、info.plist、entitlements、App Plugins、链接库、资源文件等。(详见:iOS开发:Archive、ipa 和 App 包瘦身)
瘦身的主要操作集中在可执行文件及资源文件。
资源瘦身
1.删除无用资源
使用LSUnusedResources查找无用图片。
使用方式:从github下载后直接运行,输入项目路径,点击搜索查询。
查询结果不是特别准确,建议查询后根据结果在项目中逐一查询确认,手动删除。
2.删除重复的资源
重复资源(主要指图片)不是指命名重复而是内容相同。
fdupes 是Linux下的一个工具,可以在指定的目录及子目录中查找重复的文件。fdupes通过对比文件的MD5签名,以及逐字节比较文件来识别重复内容。
- 安装fdupes。
brew install fdupes
安装较慢,需要等待一段时间。
- 查找重复的资源
fdupes -r asse文件夹位置 image文件夹位置
可直接查找项目总路径,方便查出整个项目中的相同图片及类文件(.plist及.xcconfig等也会被排查输出)。
3.无损压缩图片
- imageoptim
通过优化压缩参数,移除无用的文件数据和不必要的颜色搭配来实现无损压缩的。
- WebP图片压缩
WebP是Google提供的一种图片编码格式,通常情况下WebP格式的图片是原始JPG/PNG图片的1/3,所以对于重度依赖图片显示的应用,转换使用WebP可以节省大量的网络传输数据和时间。对于APP瘦身,使用WebP格式可能是一种方式,可以使用WebP格式的图片替代现有的图片资源,可以一定程度的节省空间。
4.图片管理方式
使用Assets.xcassets管理文件
因为它会把里边的所有 png 格式的图片压缩成一个Assets.car文件,压缩比率比其他方式管理图片要高,大大减少图片体积,同时也保证了安全性。用LaunchScreen.storyboard替换启动图片。
可执行文件瘦身
1.删除已废弃pod引用
删除弃用的库文件
减少release模式下的库引入
避免一些在debug模式下调试用的库,在release环境Archive编译至IPA包中。
pod 'MLeaksFinder', :configurations => ['Debug']
pod 'FBRetainCycleDetector', :git=> 'https://github.com/facebook/FBRetainCycleDetector.git', :configurations => ['Debug']
2.删除未使用头文件
3.删除已废弃代码类
Fui用来找出OC项目中未用到OC的头文件引用。
安装:打开终端进入fui下载文件
gem install fui
比较慢,耐心等待。
在目标路径下检索未使用类:
fui find
由于工具只是检测类文件是否被引用,故检测结果并非完全正确,如一些扩展类文件(扩展中方法置换,无需头文件引用),同时未被使用三方库文件也会输出。
建议检测出后逐文件查询排查后手动删除。
4.去除相同代码
- 安装python环境
sudo easy_install pip
- 下载安装SimHash的python工具
pip install simhash
- 下载SameCodeFinder查找相似代码
启动终端,cd 至SameCodeFinder代码文件夹,执行python SameCodeFinder.py [arg0] [arg1]
Optional
* [arg0]
* Target Directory of files should be scan
* [arg1]
* Doc Suffix of files should be scan, eg
* .m - Object-C file
* .swift - Swift file
* .java - Java file
* --detail
* show process detail of scan
* --functions
* Use Functions as code scan standard
* --max-distance=[input]
* max hamming distance to keep, default is 20
* --min-linecount=[input]
* for function scan, the function would be ignore if the total line count of the function less than min-linecount
* --output=[intput]
* Customize the output file, default is "out.txt"
示例:
python SameCodeFinder.py ~/Projects/opensource/MWPhotoBrowser/ .m --max-distance=10 --min-linecount=3 --functions --detail
结果:
在SameCodeFinder文件夹会生成一个out.txt文件,打开即可看到检测结果。
...
('YYDiskCache.m(_trimRecursively)', 'YYMemoryCache.m(_trimRecursively)', 0)
('YYCache.m(description)', 'YYMemoryCache.m(description)', 0)
...
最后一位数字代表两个文件的海明距离,数字越小说明两个文件越类似。
5.LinkMap
LinkMap文件是Xcode产生可执行文件的同时生成的链接信息,用来描述可执行文件的构造成分,包括代码段(__TEXT)和数据段(__DATA)的分布情况。
在 Xcode Target -> Build Settings -> Write Link Map File 设置为 YES,然后在 Target -> Build Settings -> Path to Link Map File 选项中设置好 LinkMap 的生成地址(一般用 build 文件夹中的默认地址就好了),archive 成功后,我们就可以在对应地址找到该次编译的 LinkMap 了
这里还可以设置Link Map存放的位置,默认的位置为:
$(TARGET_TEMP_DIR)/$(PRODUCT_NAME)-LinkMap-$(CURRENT_VARIANT)-$(CURRENT_ARCH).txt
我们可根据自己的需要自行设置该文件的位置,这里为便于查看,我设置为桌面路径。
/Users/***/Desktop/$(PRODUCT_NAME)-LinkMap-$(CURRENT_VARIANT)-$(CURRENT_ARCH).txt
路径修改完成后,command+B我们编译一下,桌面上会多一个***-LinkMap-normal-arm64.txt的文件。
但是这个文件比较多,不太好分析,我们可以通过借助第三方工具解析LinkMap。
下载完成后,运行该项目并选择路径,界面如下:
这样就能很清晰的看到编译后文件的大小了,根据情况进行文件优化。
6.编译选项优化
Optimization Level在release状态设置为Fastest,Smallest[-Os]
Strip Debug Symbols During Copy在release状态设置为YES
Strip Linked Product在release状态设为YES
Make String Read-Only在release状态设为YES
Dead Code Stripping在release状态设为YES
Deployment PostProcessing在release状态设为YES
Symbols hidden by default在release状态设为YES
7.开启BitCode
'/Users/***/Desktop/TestDemo/IFlyMSC_Dylib.framework/IFlyMSC_Dylib' does not contain bitcode. You must rebuild it with bitcode enabled (Xcode setting ENABLE_BITCODE), obtain an updated library from the vendor, or disable bitcode for this target. file '/Users/***/Desktop/TestDemo/IFlyMSC_Dylib.framework/IFlyMSC_Dylib' for architecture arm64
必须项目中使用的库文件都支持bitcode,才能设置为YES。
8.其他
- 编译的静态库瘦身
本人并未使用,在此做个记录。
详见:
iOS开发APP 瘦身之路
iOS APP安装包瘦身实践
思维导图
借用Vinecnt大神思维导图。
- 参考资料
iOS开发APP 瘦身之路
iOS APP安装包瘦身实践
iOS开发:Archive、ipa 和 App 包瘦身
iOS-APP瘦身
iOS-App瘦身
iOS App 安装包瘦身指南
iOS 应用瘦身方式总结
iOS App瘦身记录
iOS APP应用包瘦身综合实践小结