iOS优化IPA包体积大小

随着项目的不断迭代,我们APP的体积也越来越大,这势必造成下载的资源浪费,同时也给新用户下载带来流量的浪费,因此我们决定开始优化我们的IPA的体积,方便用户下载的同时,也剔除代码中的冗余资源和文件,方便后续的持续迭代。

一:资源部分

1.1 删除项目中无用资源

由于项目随着时间的推移,势必项目中会存在一些资源(图片,视频,音频等等)已经弃用或者被替换,但是没有及时去删除,因此我们首先删除这些无用资源。我们采用LSUnusedResources工具。


QQ20201225-171355.png

注意:必须勾选Ignore similar name 选项,去除相似命名规范的文件,防止这些文件被引用,但是在无任何检查的情况下被删除。

1.2 删除项目中1X的图片资源

iOS适配中,图片资源是展示原则:

1X 作用于3GS手机,手机的像素320*480,一个点为一个像素
2X iPhone4开始,尺寸为320x480,但是像素为640x960,即一个点为2个像素,所有需要2X的图片才可以保证页面不失真
3X iPhone6 plus开始,尺寸为414x736,像素为1242x2208,即一个点3个像素,所以需要3X的图片才能保证页面显示良好

作为iPhone4之前的手机,市场占有率基本上可以忽略不计。因此,我们完全有必要删除其中1x的图片资源。

二:压缩资源文件

2.1 压缩图片资源

使用无损压缩,例如 ImageOptimpngquant命令tinypng 等工具,如果涉及有损压缩最好要求设计介入进行资源检查。

本次使用ImageOptim对工程中几乎所有的图片做了一次压缩。在压缩过程中,我们发现,大部分图片都能被压缩到原来的70%左右,个别图片能获得更高的压缩比。但是打包测试后,发现IPA包的大小基本上没有任何变化。

最后在查阅了Xcode打包对于图片的资源的处理发现,在打包过程中,有一个步骤叫做compile asset catalog。在这个步骤中,Xcode会自行对png图片作压缩,并且会压缩成能够快速读取渲染的格式。我们的项目经过ImageOptim的压缩后,在compile asset catalog的过程中,Xcode会用自己的算法重新压缩,而这个”重新压缩“的过程,很可能把我们之前的压缩给覆盖。

经过测试,此类压缩基本上对后续的包体积无任何影响,因此查找其他的压缩方案。

2.2 采用Webp压缩图片资源

Webp 是由 Google 推出的图片格式,有损压缩模式下图片体积只有 jpeg 格式的 1/3,无损压缩也能减小 1/4,可以使用 cwebp 进行格式压缩转换,目前 SDWebImage、Kingfisher 都用支持该格式解析的拓展。进过测试发现压缩还是非常有效的。

从项目中随便取2张图片,进行压缩试验:

iOS优化IPA包体积大小

随着项目的不断迭代,我们APP的体积也越来越大,这势必造成下载的资源浪费,同时也给新用户下载带来流量的浪费,因此我们决定开始优化我们的IPA的体积,方便用户下载的同时,也剔除代码中的冗余资源和文件,方便后续的持续迭代。

一:资源部分

1.1 删除项目中无用资源

由于项目随着时间的推移,势必项目中会存在一些资源(图片,视频,音频等等)已经弃用或者被替换,但是没有及时去删除,因此我们首先删除这些无用资源。我们采用LSUnusedResources工具。

注意:必须勾选Ignore similar name 选项,去除相似命名规范的文件,防止这些文件被引用,但是在无任何检查的情况下被删除。

1.2 删除项目中1X的图片资源

iOS适配中,图片资源是展示原则:

1X 作用于3GS手机,手机的像素320*480,一个点为一个像素
2X iPhone4开始,尺寸为320x480,但是像素为640x960,即一个点为2个像素,所有需要2X的图片才可以保证页面不失真
3X iPhone6 plus开始,尺寸为414x736,像素为1242x2208,即一个点3个像素,所以需要3X的图片才能保证页面显示良好

作为iPhone4之前的手机,市场占有率基本上可以忽略不计。因此,我们完全有必要删除其中1x的图片资源。

二:压缩资源文件

2.1 压缩图片资源

使用无损压缩,例如 ImageOptimpngquant命令tinypng 等工具,如果涉及有损压缩最好要求设计介入进行资源检查。

本次使用ImageOptim对工程中几乎所有的图片做了一次压缩。在压缩过程中,我们发现,大部分图片都能被压缩到原来的70%左右,个别图片能获得更高的压缩比。但是打包测试后,发现IPA包的大小基本上没有任何变化。

最后在查阅了Xcode打包对于图片的资源的处理发现,在打包过程中,有一个步骤叫做compile asset catalog。在这个步骤中,Xcode会自行对png图片作压缩,并且会压缩成能够快速读取渲染的格式。我们的项目经过ImageOptim的压缩后,在compile asset catalog的过程中,Xcode会用自己的算法重新压缩,而这个”重新压缩“的过程,很可能把我们之前的压缩给覆盖。

经过测试,此类压缩基本上对后续的包体积无任何影响,因此查找其他的压缩方案。

2.2 采用Webp压缩图片资源

Webp 是由 Google 推出的图片格式,有损压缩模式下图片体积只有 jpeg 格式的 1/3,无损压缩也能减小 1/4,可以使用 cwebp 进行格式压缩转换,目前 SDWebImage、Kingfisher 都用支持该格式解析的拓展。进过测试发现压缩还是非常有效的。

从项目中随便取2张图片,进行压缩试验:

cwebp -lossless baby_info@3x.png -o ~/Desktop/new.webp
Saving file '/Users/wyz/Desktop/new.webp'
File:      baby_info@3x.png 3KB
Dimension: 51 x 51
Output:    2000 bytes (6.15 bpp)
Lossless-ARGB compressed size: 2000 bytes
  * Header size: 193 bytes, image data size: 1781
  * Precision Bits: histogram=3 transform=3 cache=9
  
cwebp -lossless baby_info@2x.png -o ~/Desktop/new2.webp
Saving file '/Users/wyz/Desktop/new2.webp'
File:      baby_info@2x.png 2KB
Dimension: 34 x 34
Output:    986 bytes (6.82 bpp)
Lossless-ARGB compressed size: 986 bytes
  * Header size: 547 bytes, image data size: 414
  * Lossless features used: PALETTE
  * Precision Bits: histogram=5 transform=5 cache=0
  * Palette size:   235

有了这个工具,确实可以大大的压缩项目中的图片资源。我们从上面的代码中看到,3K的图片可以压缩成2K,2K的最后也可以压缩不到1K,确实效率很高。项目中展示压缩过得图片,基本上看不出有任何变化,证明此压缩方案可行。

尝试删除项目中asset catalog除了启动图和icon的图标外的其他图片,经过压缩从10M左右减少到7M左右,所以看起来效果还是不错的,但是项目中图片访问只能通过bundle中来获取,这个和从asset catalog中读取图片的效率就有待商榷,毕竟asset catalog是Apple推荐的图片资源管理模式。

尝试打包在6和plus上安装时发现,安装包大小竟然一样的大小,并且在6上面的大小和优化之前基本上没有什么变化,甚至比之前的还大,显然这不是我们想要的效果。

最后查看App Store的APP在下载过程中发现,Apple会在设备下载APP是,会根据设备类型,下载IPA中不同的资源,即asset catalog中的图片资源,设备支出2X的图片,它也只会选择asset catalog中所有的2X的图片进行下载,所以我们废弃asset catalog使用后,所有的图片都进行了下载,比之前的包大也就说的过去了,因此看起来这种方法也不可取。

但是作为图片压缩一种相当不错的方式,我们完全可以用在网络图片的下载中使用。

2.3 单色图标使用tint color

Apple在iOS7推出的功能,我们可以读取一个图标,然后给它赋予一个color值,在手机屏幕上它就能显示出相应的效果。tint color适用于对单色图标进行着色,相比于其他精简图标的解决方案,tint color方便、可靠、拥有原生支持。

因此,花费一些时间排查一下简单的相同样式图片,采用tint color的方式来填充颜色,从而起到优化IPA包的效果。

2.4 资源考云端下载

Apple从iOS 9开始引入了On Demand Resource功能,即一部分图片可以被放置在苹果的服务器上,不随着app的下载而下载,直到用户真正进入到某个页面时才下载这些资源文件。

但是考虑到项目最低支持的版本,此方法只能放弃。

三:删除重复文件

我们采用fdupes工具。它是通过对比文件的MD5签名,以及逐字节比较文件来识别重复内容,fdupes有各种选项,可以实现对文件的列出、删除、替换为文件副本的硬链接等操作。
文件对比:大小对比 > 部分 MD5 签名对比 > 完整 MD5 签名对比 > 逐字节对比

安装fdupes工具,然后进行测试。

// 进入项目文件下的所有资源文件夹,找出所有重复文件,导出到txt中查看
fdupes -Sr StoryToy > ~/Desktop/123/123.txt

查看项目中的重复文件
386 bytes each:
StoryToy/Bindings/addDevice/RTBindingReadyViewController.h
StoryToy/Bindings/addDevice/RTBindingChoiceListViewController.h

341 bytes each:
StoryToy/RooboMember/VipRights/View/RBVipRightSectionReusableView.h
StoryToy/CloudResource/RooboMember/VipRights/View/RBVipRightSectionReusableView.h

1869 bytes each:
StoryToy/RooboMember/VipRights/View/RBVipRightCollectionViewCell.m
StoryToy/CloudResource/RooboMember/VipRights/View/RBVipRightCollectionViewCell.m

......

可以看出我们确实查到了一些重复文件。

四:编译相关

4.1 Valid Architectures

设置生成IPA包所包含的支持架构,如果项目中还包含32位,armv7及之前的架构,但是我们项目现在已经不支持的可以考虑删除。

4.2 App Thinning

WWDC2015 发布会上首次介绍了 App Thinning,并在 iOS9 开始应用。严格来说App Thinning不会让安装包变小,但用户安装应用时,苹果会根据用户的机型自动选择合适的资源和对应CPU架构的二进制执行文件(也就是说用户本地可执行文件不会同时存在 armv7 和 arm64),减少下载流量和安装占用空间。


QQ20201226-202726@2x.png

五:Framework优化

引入三方Framework时,会包含多个指令集,我们可以手动移除不需要的指令集。或者查找只包含我们项目指令集的framework。

首先我们需要了解不同指令集对应的设备类型:

armv7 iPhone4s之前,iPad,iPad2,iPad3(The New iPad),iPad mini,iPod Touch 3G
armv7s iPhone5,iPhone5C,iPad4(iPad with Retina Display)
arm64 iPhone5s之后的机型,iPad Air,iPad mini2(iPad mini with Retina Display)等
x86_64 模拟器64位处理器,Mac应用
I386 模拟器32位处理器,Mac应用

例如我们项目中使用的音频格式转换功能中使用的libopencore-amrnb.a的静态库,他其中包含了所有的指令集,而对于大多数移动端 App,只需要 armv7,armv7s 和 arm64 指令集就足够了。

Architectures in the fat file: /Documents/work/rtoy/ios/RToyAPP/StoryToy/StoryToy/Wechat/RTPlayer/opencore-amr/lib/libopencore-amrnb.a are: i386 x86_64 armv7 armv7s arm64

因此在项目中,我们不需要x86_64,I386 我们只需要保留其他的指令集就可以了。

//查看静态库的信息
lipo -info libopencore-amrnb.a
Architectures in the fat file: libopencore-amrnb.a are: i386 x86_64 armv7 armv7s arm64
// 抽取单一指令集的静态库
lipo libopencore-amrnb.a -thin armv7 -output libopencore-amrnbArmv7
lipo libopencore-amrnb.a -thin armv7s -output libopencore-amrnbArmv7s
lipo libopencore-amrnb.a -thin arm64 -output libopencore-amrnbArm64

// 查看生成的静态库信息
ls 
libopencore-amrnb.a libopencore-amrnbArm64  libopencore-amrnbArmv7  libopencore-amrnbArmv7s libopencore-amrwb.a

lipo -info libopencore-amrnbArmv7
Non-fat file: libopencore-amrnbArmv7 is architecture: armv7

// 合成完整的静态库
lipo -create libopencore-amrnbArm64 libopencore-amrnbArmv7 libopencore-amrnbArmv7s -output nb/libopencore-amrnb.a

// 查看新生成的静态库信息
cd nb;ls
libopencore-amrnb.a
lipo -info libopencore-amrnb.a
Architectures in the fat file: libopencore-amrnb.a are: armv7 armv7s arm64

移除多余的指令集后,静态库大小从 4.8MB 降到 3.3MB,效果还是非常完美的。

六:结语

经过本次尝试,IPA包体积都有5%~20%不同程度的减小,当然优化的空间依然巨大。在实际项目瘦身过程中,上面列举的方式不一定都适用。因此对于项目瘦身,还是需要怀着一颗谨慎的心,谨慎检验每一次的尝试。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 201,552评论 5 474
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,666评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,519评论 0 334
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,180评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,205评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,344评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,781评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,449评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,635评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,467评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,515评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,217评论 3 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,775评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,851评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,084评论 1 258
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,637评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,204评论 2 341

推荐阅读更多精彩内容