目录:
- 000 - 苹果提供的 App Thinning (了解)
- 001 - 项目结构介绍
- 002 - 变更图片文件的导入方式
- 003 - 快速删除项目中不用的图片资源
- 004 - 图片无损压缩
- 005 - 使用 fui 找到应用中未使用的类
- 006 - LinkMap解析工具:检查每个类占用大小 (代码瘦身 )
前言:关于项目结构与应用包瘦身的学习
面对如今不断迭代的iOS APP,在产品需求以及功能模块的持续扩大下,应用包大小也会随之变得越来越大,当代码量达到一定程度后,对于一个持续性的大型项目来说应用包瘦身是一个迫在眉睫的问题。
当我们谈及应用包瘦身,无非就是从两个层面应对,一个是资源级别的优化,一个就是代码级别的优化,接下来我们就从这两个方面下手。
对
App
包瘦身处理是为了减少包的大小,节约用户下载App
流量。在App Store
下载App
,如果超过了150MB就必须在Wi-Fi环境下载或更新,这样如果``超过了150M,可能就会间接失去了大部分用户。如果我们的App
要兼容iOS7和iOS 8,苹果官方规定:主二进制text段的大小不能超过60M,如果超过这个标准,就没办法向App Strore
提交审核。下面这张表格列举了当前国内外的部分常用App的包大小。
通过上面的表格可以看出目前包少于150M的只有网易云音乐,Instagram,Twitter。那么作为开发者可以通过哪些方法对自己的App包大小做优化处理呢?
内容:
000 - 苹果提供的 App Thinning
我们知道不同的设备的屏幕大小、分辨率、CPU、GPU、硬盘大小等都不相同。针对这种情况,苹果官方为开发者提供了 App Thinning技术,对于不同设备提供只适用当前设备的包为用户提供下载。如iPhone 5C只会下载适用于32位运行芯片的库和2x的图片资源的包,iPhone 8P则会下载适用于64位的库和3x的图片资源。
- 苹果关于App Thinning的介绍请看:
App Thinning in Xcode视频
App Thinning官方文档
一、App Thinning 基本介绍
App Thinning有三种方式: 1. App Slicing 2. Bitcode 3. On-Demand Resources
App Slicing:
iOS9之后苹果官方出的解决方案,在向iTunes Connect上传App包后,对App做切割处理,创建不同的变体包,这样就可以适用到不同的设备;itcode:
也是iOS9之后苹果给出的解决方案,针对特定的设备进行包大小优化。On-Demand Resources:
主要是为又下多关卡的情况服务的,On-Demand Resources会根据用户的关卡下载进度下载随后几个关卡的资源,并且已经过关的资源会被干掉,这样可以减少初始App包的大小。
二、那么如何在项目中适用App Thinning呢?
2.1 - Slicing的使用
在使用
App Slicing
的时候,大部分工作是由Xcode
和App Store
来完成的,开发者本身不需要做任何事情
。在开发中只需要创建xcassets目录,然后将图片加入其中即可
。在创建一个工程的时候Xcode会默认为开发者创建一个名为Assets.xcassets的目录,在开发过程中只要把图片资源加入其中即可。当然也可以自己新建,选中工程目录
New File--->Resources--->Asset Catalog
即可新建一个。我们在使用
xcassets
时,添加对应的2x分辨率和3x分辨率的图片,会在上传到App Store
后被创建成不同安装包以减少App
安装包的大小。同时苹果会自动根据的设备不同,在创建的安装包中自动加入当前设备需要的芯片指令集架构文件。
2.2 - Bitcode使用
Bitcode: Apple Developer Bitcode说明
bitcode
是介于源码和机器码之间,在LLVM
中的IR(Intermediate Representation)
这层,由编译器前端clang
生成,交给LLVM
优化器优化后交给后端生成CPU
相应指令。一般情况下,在
iOS9
之后,新建一个工程,Xcode
会默认设置Bitcode
。由Xcode
将Bitcode
提供给Apple
,由他们针对各种机型(包括新机型)的CPU对代码做二次优化,其本身不会增加包体积,上传的二进制文件会变大,但是不会影响用户的下载大小。如果开启
Bitcode
,相应的,所有使用的pod
都需要开启Bitcode
,Bitcode
必须是完整的,否则就是无效的,编译阶段就会报错。开启
Bitcode
选项后,在debug
模式下不会打进Bitcode
,只有在Archive
时才会。
2.3 - On-Demand Resources的使用
将图片、音频等资源文件分离出来,开发阶段将资源按照ResourceTag区分,存放在苹果的服务器上。App按需要发起请求,由操作系统来管理下载和存储,一般用于游戏资源或者内购。
优点:
- 包体积更小,为设备省更多的存储控件 - 懒加载(Game -> level -> download current resources) - 很少使用的资源可以放在服务器(Tutorial)
缺点:
- 资源需要从苹果服务器下载 - 资源需要按tag区分,制定相应的配置策略 - 代码中管理何时下载,何时释放,增加了资源管理的复杂度
备注:
001 - 项目结构介绍
项目本身首先划分功能区以Page、Core、App划分
1、Page存储应用的模块,包含首页、个人中心等,每个模块下再以Controller、View、Model划分
2、Core 存储着一些与项目业务、界面无关的类,包括分类、宏定义、封装的请求基类等
3、App则存储着一些与项目相关的类,包括API、Base基类等
002 - 变更图片文件的导入方式
资源文件有很多种方案加入到工程项目中:
1. Assets.xcassets。
- 只支持png格式的图片;
- 图片只支持[UIImage imageNamed]的方式实例化,但是不能从Bundle中加载;
- 在编译时,Images.xcassets中的所有文件会被打包为Assets.car的文件。
2. CreateGroup
- 黄色文件夹图标;Xcode中分文件夹,Bundle中都在同一个文件夹下,因此,不能出现文件重名的情况;
- 可以直接使用[NSBundle mainBundle]作为资源路径,效率高;
- 可以使用[UIImage imageNamed:]加载图像。
3. CreateFolderRefences
- 蓝色文件夹;Xcode中分文件夹,Bundle中同样分文件夹,因此,可以出现文件重名的情况;
- 需要在[NSBundle mainBundle]的基础上拼接实际的路径,效率较差;
- 不能使用[UIImage imageNamed:]加载图像。
【说明】:蓝色文件夹只是将文件单纯的创建了引用,这些文件不会被编译,所以在使用的时候需要加入其路径。
4. PDFs矢量图(Xcode6+)
5. Bundle(包)
对于上面这几种不同的导入方式,会对打出的包的大小有影响么?
经过测试得知:CreateGroup、CreateFolderRefences两种方式打出来的包,图片都会直接放在.app文件中,所以打包前后,图片的大小不会改变。而加入到Assets.xcassets中的方法则不同,打包后,在.app中会生成Assets.car文件来存储Assets.xcassets中的图片,并且文件大小也大大降低。
值得留意的是,在将图片资源移到Assets.xcassets管理的时候,一般情况下会自动生成与图片名称相同的,比如loading@2x.png和loading@3x.png会自动放置到一个同名的loading文件夹中。然而有一些不规则命名的图片,会出现一些奇怪的问题:
图片名称为ios-f2-8-004的图片,放到Images.xcassets中,会自动生成调用的图片名是ios-f2-8-4,最后一位的004,被替换成4,然而在类文件中引用的是[UIImage imageNamed:@"ios-f2-8-004.png"],这样会找不到图片;
图片名称为ios-f6-的图片,放到Images.xcassets中,会自动生成调用的图片名是ios-f6,这样也会找不到图片。
因此在移动的时候,一定要细致对比。
备注
通过CreateGroup、CreateFolderRefences两种方式打出来的包,图片资源不会做改动,直接放在.app包文件中,打包的前后图片资源大小不会改变。
而加入到Assets.xcassets中的方式是在。app中生成Asset.car文件来存储放入的图片资源,是对图片资源进行了一次压缩,因此文件大小会降低,
综上所述,尽量使用Asset.xcassets的方式来导入资源文件能有效的控制APP包的大小。
003- 快速删除项目中不用的图片资源
开发中,由于不断地迭代,工程中必不可少的会有很多用不到的图片资源,使工程包的文件越来越大
如果一张张查询清理,这样很耗时,也很麻烦。推荐给大家一个方法,不到3分钟,就能清理所有的用不到的图片资源。首先先去下载一个大牛写的mac应用,运行打开,传送门
操作页面如下
操作步骤详解:
1.下载并打开应用就会显示如上图一个界面。 2.点击Browse,选择工程所在目录。 3.点击search按钮,一会所有工程中没有用到图片就被搜索出来了。 4.选择需要删除的图片,点击Delete就可以删除了,这时候你再进入工程中查看,图片已经没有了。
备注 删除图片的时候,也要仔细些,不要把自己手动集成第三方中的图片删掉了,最好提前备份一份。
004 - 图片无损压缩
使用的工具是 ImageOptim ,点击链接下载
将项目图片拖入ImageOptim优化即可,详细的操作步骤在下载链接官网中有所描述
ImageOptim 主要作用是删除膨胀的元数据。通过压缩图像节省磁盘空间和带宽,而不会降低质量。
ImageOptim使用其优化版本覆盖文件。这是安全的,因为ImageOptim可以保持图像质量。如果您对此不满意,可以在将文件放入ImageOptim之前创建文件的副本。此外,作为预防措施,ImageOptim会将原始文件放入“废纸篓”中,因此您可以根据需要轻松恢复它们。
实验图例
1.无损压缩之前文件大小
2.正在进行无损压缩
3.无损压缩完毕
4.压缩之后的文件大小
005 - 使用 fui 找到应用中未使用的类
为了给APP提速,需要定期清理不用的类 fui(Find Unused Imports)是开源项目能很好的分析出不再使用的类,准确率非常高,唯一的问题是它处理不了动态库和静态库里提供的类,也处理不了C++的类模板。
使用方法是在Terminal中cd到项目所在的目录,然后执行fui find,然后等上那么几分钟(需要好几分钟甚至需要更长的时间),就可以得到一个列表了。 由于这个工具还不是100%靠谱,可根据这个列表,在Xcode中手动检查并删除不再用到的类。
fui的github链接 使用
//安装 fui 工具 在终端中执行命令 sudo gem install fui -n /usr/local/bin fui usage: https://github.com/dblock/fui 到工程目录下,执行 fui find 命令,可以找出所有的没有用到的class文件
总体,感觉还有些类不准确,可以自己去仔细分辨。
006 - LinkMap解析工具:检查每个类占用大小 (代码瘦身 )
Link Map File中文直译为链接映射文件,它是在Xcode生成可执行文件的同时生成的链接信息文件,用于描述可执行文件的构造部分,包括了代码段和数据段的分布情况。
应用步骤:
1、打开LinkMap.xcodeproj,并运行,就可以看到工具界面
2、点击“选择文件”按钮,选择LinkMap文件(如何生成LinkMap详见下方的:如何获得LinkMap文件)
3、点击“开始”按钮,就可以看到每个类/静态库所占用的空间大小(如上图)
4、点击“输出文件”,可以将结果输出到文本文档中
如何获得LinkMap文件
1.Xcode在生成可执行文件的时候默认情况下不生成该文件,需要开发者手动设置Target --> Build Setting --> Write Link Map File为YES:
2.工程编译完成后,在编译目录里找到Link Map文件(txt类型)
默认的文件地址:~/Library/Developer/Xcode/DerivedData/XXX-xxxxxxxxxxxxx/Build/Intermediates/XXX.build/Debug-iphoneos/XXX.build/ \n\
【扩展学习链接】
参考文章