包大小优化

背景知识

App的大小分为下载大小和安装大小。
下载大小指的是App压缩包(.ipa)所占的空间大小。用户下载的是压缩包,下载完成后会自动解压,安装大小就是指压缩包解压后的大小。
下载大小如果超过200MB,iOS13以下无法通过蜂窝网络下载;iOS13以上会通过用户手动设置才可以下载。

App Connect上的文件大小

包大小优化

网上有很多包大小优化的方案,我看了很多博客,根据博客总结一下包大小优化相关的操作,如下图。

包大小优化.png

Xcode编译设置

  1. 去掉异常支持,Build Setting中Enable C++ Exceptions和Enable Objective-C Exceptions设置为NO,Other C Flags添加-fno-exceptions
去除异常支持.png

注意⚠️:Enable C++ Excptions和Enable Objective-C Exceptions是指项目支持异常处理,关闭后try cache、throw、包括宏定义try{}、@finally{}、@strongify会报错。
-fno-exceptions的意思是禁用异常机制,参考gcc,同样,当项目中有try thorw的时候,就不要设置这个选项为NO。

Before detailing the library support for -fno-exceptions, first a passing note on the things lost when this flag is used: it will break exceptions trying to pass through code compiled with -fno-exceptions whether or not that code has any try or catch constructs. If you might have some code that throws, you shouldn't use -fno-exceptions. If you have some code that uses try or catch, you shouldn't use -fno-exceptions.

2.Build Settings -> Architectures,在Excluded Architectures中设置Release模式下 Any iOS SDK -> armv7,设置之后在Release下把armv7排除。

Architetures设置.png

armv6: iPhone, iPhone 3G, iPod 1G/2G
armv7: iPhone 3GS, iPhone 4, iPhone 4S, iPod 3G/4G/5G, iPad, iPad 2, iPad 3, iPad Mini
armv7s: iPhone 5, iPhone 5c, iPad 4
arm64: iPhone X,iPhone 8(Plus),iPhone 7(Plus),iPhone 6(Plus),iPhone 6s(Plus), iPhone 5s, iPad Air(2), Retina iPad Mini(2,3)
arm64e: XS/XS Max/XR/ iPhone 11, iPhone 11 pro x86_64: 模拟器64位处理器 i386: 模拟器32位处理器

这里:iOS9之后推出了App Thinning,在这过程中苹果已经帮忙去掉armv7了。

3.Build Settings -> Generate Debug Symbols设置为NO

调试符号.png

Generate Debug Symbols是生成调试符号,断点不能用,最后不能生成DSYM文件(DSYM文件是指具有调试信息的目标文件)。建议不要设置为NO。

  1. Build Settings -> Deployment Postprocessing,Debug模式下设置NO,Release下设为YES
    Deployment Postprocessing是Strip配置的总开关
截屏2022-08-11 下午5.12.49.png

Build Settings -> Strip Linked Product,Debug下设置为NO,Release下设置为YES。
设置为Yes时,对最后的二进制文件进行strip,去除不必要的符号信息。
注意⚠️:去除了符号信息之后需要使用dSYM来进行符号化,所以需要将 Debug Information Format 修改为DWARF with dSYM file(Release下),如果在Debug下设置为DWARF with dSYM file那么在崩溃时将无法看到堆栈信息。

Build Settings -> Strip Debug Symbols During Copy,Debug下设置为NO,Release下设置为YES
文件拷贝编译阶段是否进行strip,设置为YES之后,会把拷贝进项目包的三方库、资源或者Extension的Debug Symbol去除。

5.Build Settings -> Symbols Hidden by Default,Debug模式下设置为NO,Release下设置为YES
Symbols Hidden by Default会把所有符号都定义成"private extern",移除符号信息

symbols.png

6.Build Settings -> Make Strings Read-Only设置为YES
复用字符串字面量

截屏2022-08-11 下午5.16.55.png

7.Build Settings -> Dead Code Stripping设置为YES
消除无效代码,C/C++/Swift 等静态语言编译器会在 link 的时候移除未使用的代码,对于OC等动态语言是无效的

截屏2022-08-11 下午5.17.30.png
  1. Asset Catalog Compiler编译设置优化,Build Settings ->
    Compiler - Options 中Optimization改为space
    这个选项可以改变actool在构建Assets.car时选取的编码压缩算法,减少包大小
截屏2022-08-11 下午5.18.55.png

9.Build Settins -> Optimization Level改为-Oz

Optimization Level默认为-Os,-Oz是Xcode 11之后才出现的编译优化选项,核心原理是对重复的连续机器指令外联成函数进行复用,因此开启Oz,能减少二进制的大小,但同时会带来执行效率但额外消耗。

Optimization.png

Optimization Level各参数优化的选择对比,如下图,对于性能要求高的,建议选择-O2和-O3,对于包大小敏感的,可选择-Os和-Oz,默认-Os是性能和大小平衡比较好的。最终选择什么,需要读者根据自己实际项目而定。

参数对比图.png

Pod设置

在OC的项目中,Podfile如果引用了Swift的第三方库,一般都会直接打开use_frameworks!,对应的Pod中所有的库都会
打包成动态库,以及Swift和OC库的依赖问题会导致依赖库增加,会造成包体积增大。所以我们可以有优化为针对单个Swift库使用use_frameworks!

Podfile修改.png

我按照上述修改后,pod install报错了,修改方法如下图。

pod报错修改方法.png

资源优化

删除未使用的类

查看了一些文档后,我使用了python脚本的方法来查找项目中未使用的类。脚本地址如下:
脚本地址
执行方法:
1.cd到脚本所在文件夹中
2.运行下需要检测的项目后按照如下步骤找到.app文件所在文件夹

app文件位置右键显示.png

3.执行python脚本

python FindClassUnRefs.py -p /Users/a58/Library/Developer/Xcode/DerivedData/XXX-bqqoxganvkvgwuefbskxsbvnxlnn/Build/Products/Debug-iphonesimulator/XXX.app -w JD,BD,AL

参数说明:
-p Xcode运行之后的,项目Product路径
-w 结果白名单处理,检测结果,只想要以什么开头的类,多个用逗号隔开,比如JD,BD,AL
-b 结果黑名单处理,检测结果,不想要以什么开头的类,多个用逗号隔开,比如Pod,AF,SD
-w 和 -b 不能共存,共存会报错

用这个方法并未查找到未使用的category,并且还是需要在项目中进行搜索判断是否使用该类,结果并不完全准确。

删除未使用图片

通过工具LSUnusedResources,运行后,输入项目文件位置,即可查找未使用的图片。
LSUnusedResources下载地址

原理大致是遍历资源目录下后缀 ["imageset", "jpg", "png"...] 的文件,然后在源文件 ["m", "swift", "xib", "storyboard"...] 中字符串匹配,无匹配则是无用的资源文件。

使用时注意勾选Ignore similar name,然后点击右上角的Browse选中要扫描的项目地址,点击右下角的search,就会开始扫描,结果会在底部Unused Results中展示出来,然后CMD+A全选,export,导出到一个文本文件中。也可以在对应单条Item上面双击,会打开对应的文件夹。建议删除前在项目中搜索确认,是否确实没有使用(类似字符串中间替换的可能会被扫描出来,所以删除前需要确认)

压缩图片

可以通过以下网站压缩图片
tinyPNG

tinyPNG网站.png

总结:
以上就是我包大小优化的过程,查看了一些博客,然后根据博客上所说的进行修改。以下是我打包两个.ipa包的大小对照图,从32M优化到了19.8M。

ipa文件大小对比.png

Mach-O文件

我们讲.ipa文件后缀修改为.zip后解压,会看到文件中所包含的内容。主要有codeSignature、Assets.car、还有一个exe文件,这个文件的格式是Mach-O。
在这里也可以看到nib文件,因为项目中使用xib文件绘制UI。由此可以知道,如果想要控制包大小,最好不要使用xib文件(个人理解)。

解压文件.jpg

可以使用MachView来查看Mach-O文件,MachView下载地址如下
MachView下载地址

Mach-O文件主要包括三部分:

  • Header:文件基本属性、CPU的类型、Load Commands的个数等。
  • Load Commands:由多条Load Command组成,它们描述了Data在二进制文件和虚拟内存中布局,有了这个布局就能够知道Data的排布情况。
  • Data:存储的实际内容,主要是程序的指令和数据,按照Load Commands描述排布。
Mach-O文件组成.png
Load Commands内容.png

使用以下指令可以查看Mach-O文件Data部分的结构和大小信息。

xcrun size -lm /Users/boyankeji/Downloads/LianCheng\ 2022-08-09\ 16-43-21/Payload/连成物联.app/连成物联 
查看结果.png

如图所示,主要包括了4部分:

  • __PAGEZERO
  • __TEXT
  • __DATA
  • __LINKEDIT

__PAGEZERO在内存中不可读不可写,用于捕获NULL指针。它并不占用Data的空间。

__TEXT、__DATA保存代码的指令和数据。

__LINKEDIT包含启动App需要的信息。

今日头条优化实践: iOS 包大小二进制优化,一行代码减少 60 MB 下载大小这个博客中的包大小优化方法,主要就是将__TEXT段进行迁移。

其中原理是:

When your app is approved for the App Store, it is encrypted with DRM and recompressed. The added encryption and DRM affects the ability to compress your binary, and as a result you may see a larger App Store file size for your binary than the binary you uploaded on App Store Connect. The exact final size for your app cannot be determined in advance to the accuracy of a single byte.

我们将项目进行Archive后生成.xcarchive文件,文件上传到App Store Connect后,苹果会对可执行文件进行加密,然后再将App压缩成.ipa文件,然后发布到App Store。
加密会影响可执行文件的压缩效率,从而导致ipa大小增加,而这种加密效果几乎没用。
Mach-O 文件代码的解密发生在 Mach-O 文件被加载的时候,由 Mach Loader 进行。Mach Loader 会读取 Mach-O 中的 LC_ENCRYPTION_INFO 这条 Load Command 来判断可执行文件是否加密。

判断ipa文件是否加密.png

cryptid 表示加密方法为 1,如果为 0 表示不加密。

通过以下指令可以查看Load Commands

otool -l /Users/boyankeji/Downloads/LianCheng\ 2022-08-09\ 16-43-21/Payload/连成物联.app/连成物联

我们通过查看__TEXT的filesize,通过计算可以知道加密的内容主要在__TEXT上。所以我们将__TEXT移走可以达到减少包大小的目的。

__TEXT.png

注意⚠️:
苹果在 iOS 13 已经对下载大小做了优化,所以本方案无法再对 iOS 13 的设备的下载大小进一步优化。
即,若用户的设备 < iOS 13,那么本方案可以减少该设备上 App 32~34%的下载大小;
若用户的设备 >= iOS 13,本方案不会对该设备的 App 的下载大小有进一步优化,也不会有负面影响。

包大小优化总结

根据查找的博客来看,包大小优化主要是三部分:

  1. Xcode中删除编译需要的Symbols、Debug符号等;
  2. 对资源的控制,不要重复引入图片、过大的资源文件需要进行压缩;未用的代码、类需要及时删除;
  3. 黑科技,根据头条给出的方案,迁移__TEXT
    以上是我根据最近一段时间的学习总结的,在学习的工程中,会发现自己对程序的构建、脚本的使用、Mach-O文件等都不太了解,现在通过学习感觉也只是皮毛的阶段。以后如果有时间需要更加深度的学习。
    通过学习包大小优化的内容,以后在开发的过程中需要增加包大小优化的意识。

学习链接

App Store上的包大小
分析iOS包大小优化
iOS 脚本查看项目中未使用的类
iOS检测项目中无用类和方法
今日头条优化实践: iOS 包大小二进制优化,一行代码减少 60 MB 下载大小
iOS底层探索- Mach-O文件

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

推荐阅读更多精彩内容

  • 背景 包大小优化是项目开发中不可避免会遇到的,网上关于包大小优化的文章很多,每篇文章说的都不尽相同,笔者曾经根据网...
    大菠萝_DABLO阅读 4,914评论 0 12
  • 背景 移动开发中,对于包大小优化是项目开发中需要考虑的,尤其对于航母级App,比如QQ、手淘等。网上关于包大小优化...
    virusbo阅读 4,266评论 1 18
  • 官方App Thining App Thining会根据不同的设备提供相应的App包进行下载。 App Thinn...
    拧发条鸟xds阅读 583评论 0 3
  • 1.官方 App Thinning 官方推出的改善App下载进程的技术 因为现在ios设备屏幕尺寸,分辨率越来越多...
    crazyfox阅读 507评论 0 5
  • 这里记录下个人根据相关文档(基本参照今日头条分享的文章,链接在底部)对开发的某个app进行包大小优化的实践过程,这...
    QYCD阅读 1,041评论 0 3