一、前语

咱们项目的APP经过不同团队的迭代开发,以及后续因为事务调整,将另一款APP也融入到主APP中(因为迭代时间以及前史原因,两个APP选用最粗犷的代码合并方法融合在一起),使得包体积由本来的100多M,激增到306M,远远超过了苹果规定的200M的下载约束,因而不得不开端考虑进行体积优化了(本期只讲计划,包体检测以及优化计划原理后期逐渐更新)。

二、包体积优化的必要性

1. App Store的约束

关于运用蜂窝数据网络下载运用的用户,App Store有一个初始下载约束,一般为200MB。这意味着运用的初始下载巨细不能超过这个约束,超过约束的内容需求用户在衔接 Wi-Fi 后才干下载(iOS13之前,iOS13开端能够设置),这大大影响了用户的下载志愿。

2. 用户体会

较小的运用包体积能够供给更快的下载、安装和更新速度,然后提升用户体会。用户更倾向于挑选下载和保留体积较小的运用,以节省设备存储空间。

3. 下载和安装时间

大型运用需求更长的下载和安装时间,可能会让用户感到不耐烦,乃至放弃下载。小巧的运用能够更快地进入用户设备,降低了用户等候的时间。

4. 设备存储空间

用户设备的存储空间是有限的资源。运用体积较大可能会占用大量存储空间,导致用户不得不删去其他运用或文件来腾出空间,或许购买更大容量的设备。

5. 移动数据耗费

下载和更新大型运用可能会耗费用户的移动数据流量,对用户来说可能是额定的本钱。小型运用能够减少数据运用。

6. 市场竞争

在App Store中,用户往往会比较不同运用的巨细。较小的运用可能在用户眼中更具吸引力,有助于运用在激烈的市场竞争中锋芒毕露。

7. 更新办理:

频频的大型更新可能会打扰用户并增加用户流失的危险。

包体积检查:用户侧看到的巨细

iOS 包体积优化方案与实践(一)

开发人员从appstoreconnect上看到的是两个体积,下载巨细和安装巨细。 这儿的巨细分为两个口径:
下载巨细 和 安装巨细。

依据网页上的说明:
安装巨细 是这个 app 安装后,会占用的磁盘巨细;
下载巨细 是 app 经过紧缩后的巨细。

依据经历,用户在 app store 上看到的巨细,便是 itunes connect 后台中显现的 安装巨细。

而令开发者在意的,“超过 200 MB 的 app 必须衔接至无线局域网才干下载”的规则中的 200 MB,指的其实是 下载巨细。

iOS 包体积优化方案与实践(一)

三、包体组成部分

iOS 包体积优化方案与实践(一)
经过上图,能够明晰看到可优化的点,接下来逐渐优化就好了。

3.1 资源优化

3.1.1 废弃资源删去

因为前史原因,存在很多僵尸类以及资源文件,逐渐删去就行了,删去的时分能够运用一些检测东西批量删去,这儿不做赘述。无用的类删去后,对应的资源也能够一起删去。

3.1.2 资源优化

资源优化无非便是那几种,咱们选用的是紧缩文件和本地资源网络化,其实也能够经过更改图片格式的方法,改成webp,可是需求代码支撑,因为各方本钱比较高,暂时没有尝试。

运用东西将图片进行无损紧缩,紧缩的过程发现很多很大的图,有的一张乃至几M,这个就很浪费资源了。经过几轮紧缩,整体资源减少了大几M,接下来便是资源网络化了(网络化之前的紧缩为了更快的下载资源)。

这部分也分为两块,能够运用自己的图片服务器进行上传,也能够运用苹果官方供给的On-Demand Resource计划,咱们项目中两种计划都用到了,下面就介绍一下两种计划的不同点。

3.1.2.1 On-Demand Resource

在介绍之前,先说两点

1、ODR中的资源是在APP打包的时分确定的,不进行版本更新就无法更新这些资源。
2、ODR的资源是存放在苹果Server的,咱们不需求再用自己的服务器。

如何开启:在build settings中搜索assets,将Enable On Demand Resources设置为YES,然后再Resource Tags下面增加对应的分组就好了。

iOS 包体积优化方案与实践(一)

On-Demand Resource的三种标签:
  • Initial install tags.此种标签的资源,会跟着App从App Store下载而下载,可是会影响App的ipa巨细,也便是说此种资源会包含在ipa内。
  • Prefetch tag order.此种标签会在App下载后,开端下载相应的资源,下载是存在次序的,后面会说明。此种资源并不会影响ipa的巨细,也便是说此种资源并不包含在ipa内。
  • Dowloaded only on demand. 此种标签下的资源,会在必要的时分,自动触发下载,这是咱们开发者自己操控下载时机的。

咱们项目中选用的是第二和第三种。先说下原因:上面介绍了,咱们有个第三方的大项目集成到主项目中了,并且翻开的入口很会集,因而,该项目的一切资源都能够会集统一处理。咱们在项目启动的时分,会加载这个项目中的部分资源(必要的),在点击跳转的时分会判别是否下载完结,假如没有,则继续下载直到下载完结为止。因为咱们每个事务模块的调用相对会集且单一,因而在入口处处理就能够了,假如很涣散,不建议用这种方法处理。

这种计划关于咱们来说,只合适去做一些统一模块的处理,把整个模块的资源包统一下载下来,一旦失败就需求在事务调用的时分从头下,代码逻辑比较重,无法做到无痕处理,关于老项目来说一些涣散的事务模块比较难保护,因而咱们只用在了乐屋部分的事务处理。其他模块则选用第二种方法。

3.1.2.2 长途资源服务器

将本地图片资源放到长途服务器,按需下载,长处是能够依据事务需求按需加载,运用sd等第三方的图片处理计划做几级缓存,这样既节省了流量资源也节省了内存资源(实质便是加载网络图片的那套逻辑)。缺陷便是需求保护网络资源,以及做版本办理,长途冗余的资源要定时铲除。

这部分内容咱们将图片按巨细以及模块做了个分类,10k以上的资源全部迁移到长途,以下的依然本地存储,这部分优化掉接近20M的空间。

3.1.3 符号剥离

stripiOS中的作用是剥掉目标文件中一些符号信息和调试信息,使文件变小。

strip:移除指定符号。在Xcode中默认strip是在Archive的时分才会生效,移除对应符号

iOS 包体积优化方案与实践(一)

值得注意的是,并不是一切文件的符号都是能够剥离的:

动态库 不能strip大局符号、因为大局符号要作为导出符号。

App中 直接符号表中的符号不能strip;那么App中 本地符号、大局符号都能够strip。

静态库 = .o文件合集,存在重定位符号表,这个表中的数据也是不能strip的。所以 .o文件中能strip的是调试符号。

3.1.3.1 在xcode中配置

Build Setting中设置Deployment Postprocessing,在编译阶段就会运行strip

iOS 包体积优化方案与实践(一)

设置Strip Debug Symbols During Copy

iOS 包体积优化方案与实践(一)

当运用在编译阶段copy了某些二进制文件时,翻开该选项会脱掉该二进制的调试符号。可是不会脱去链接的最终产品(可执行文件\动态库)的符号信息。要脱去链接的产品(App的可执行文件)的符号信息。

设置Strip Linked Product

iOS 包体积优化方案与实践(一)

假如没有翻开Deployment Postprocessing,则会在Archive处理链接的最终产品(可执行文件)的符号信息。不然,在链接完结之后就会处理符号信息

设置Strip Style(符号剥离等级),它会在生成可执行文件后进行优化,相当于对Mach-O文件进行修改

iOS 包体积优化方案与实践(一)

All Symbols:除了直接符号表中运用的符号,其他符号都移除(上架App运用)

Non-Global Symbols:除了大局符号都能够移除 (动态库运用)

Debugging Symbols:移除调试符号(静态库运用)

因为 App在链接静态库的时分,.o文件的合集会把.o中的一切符号、包括重定位的符号,都放到App的符号表中。因而可能变成了大局符号、本地符号、导出符号。那么依据strip的原理、在静态库中一切的符号都能够被剥离. 而动态库中一切的符号都被放到App的直接符号表中、那么再去strip的时分、动态库中的死代码将不能被剥离。

3.1.3.2 终端执行

还有一种方法,是直接找到framework的二进制文件路径,执行 xcrun strip -xS AAA -o AAA_strip,AAA是原始文件名称,-o后面是导出后的名称,可是这种方法会导致部分文件签名问题,需求从头签名。用这种方法,咱们包体积减了20多M。

四、总结

经过以上方法,安装包由306M减少到了200M,下载包在80M左右,效果还是很明显的。 在实践项目减肥过程中,上面罗列的方法纷歧定都适用。比方图片放在长途,需求搭建自己的长途库,或许运用阿里云,可是并不是一切的图片都合适。例如当项目具有动态化,许多类和方法都不会在代码中直接产生引用,而可能是经过接口方法下发数据来运用,假如没有配置表会简单产生误删。有的资源是在xib中或许Swift中,有的东西检测不到简单误删,所以在删去资源的时分一定要慎之又慎。。。。安全第一。。。。

东西汇总

  • 功能检测:WBBlades

  • 无用图片检测:LSUnusedResources

  • 图片紧缩:ImageOptim、tinypng、Webp

  • 检查Mach-O内容:MachOView

  • 静态检测代码:LinkMap结合Mach-O 或 Appcode静态检测