Qnext大会 | App Slicing在携程APP上的实践

2018-03-16 11:20:55 浏览数 (1)

原创专栏|祁一鸣

2016年4月加入携程, 任机票研发部技术专家。毕业于美国常春藤名校Dartmouth College本科,曾先后在硅谷的Oracle, Yahoo!和Salesforce总部效力过。从scratch到delivery完成过的最成功的产品是年销售额超1亿美金的商业社区网站模板。平时喜欢吃冰激凌和甜甜圈,也蛮喜欢上海野兽派的花。

APP Slicing是苹果在2015年推出的基于iOS 9平台的新的打包功能。Slicing本身是一种对不同用户的iPhone设备生成并下发不同版本app安装包的过程。当用户在苹果应用商城下载一款APP的时候,如果这款App实现了Slicing的功能,那么用户下载的app bundle里的静态资源是对用户当前手机版本适配的。譬如,经历过Slicing的安装包里只会有适配于当前手机仅一种分辨率的图片,而不是一倍图,两倍图,甚至是三倍图片同时共存,从而优化并缩小了App安装包的大小。 这就是本次分享的主题思想。

1. iOS App安装包解析

说到一个iOS App的安装包, 首先要了解一下.ipa文件的概念。 ipa文件全名 iOS application archive,是iOS平台下所有应用可执行文件以及资源文件的打包文件。 要了解一个iOS App里的内容, 首先要去解析ipa文件。

ipa文件里的内容包括:

-- app binary可执行文件

-- Nib文件

-- db数据库文件

-- 图片文件

  • Assets.car
  • png, jpeg文件等等

-- plist属性文件

-- 其他

对于运用了Slicing功能的App, 图片资源文件会被压缩并统一储存在于ipa文件里一个名为Assets.car的特殊文件夹里。 反之, 每张图片资源文件会独立存在于ipa文件里。

2. 通过Asset Catalog处理图片实现App Slicing的想法

Xcode 5 推出了Asset Catalog,一款帮助开发者在App里管理图片资源的工具。

如上图,选中Xcode工程中的Images.xcassets文件夹,选择添加 New Image Set,为这个Image Set取个名字(譬如Oval), 再将不同分辨率的图片 (2x, 3x)拖到指定的2x和3x图片区域, 便完成了通过Asset Catalog方法添加图片的操作。以此类推, 如果每张图片都是按这样的方式添加的,那么将Xcode中的工程archive并提交到苹果应用商城之后,Slicing的过程就会自动被触发。苹果应用商城会生成不同variant版本的安装包, 用户下载的app安装包时也会根据自身的设备版本(iphone5, iphone6s plus, etc),仅储存一种适配分辨率的图片资源。譬如,通过iPhone 6s plus下载的App安装包里只有3x的图片资源, 通过iPhone 5s下载的APP安装包里只有2x的图片资源。

3. App Slicing在携程APP上的实践

说了这么多,似乎只要在App里添加图片的时候使用Asset Catalog就可以自动达到Slicing的功能了。 那本次的分享话题也就结束了。 谢谢大家。

确实,如果是新开发一款从零到一的APP,每次在工程中添加图片资源的时候只要按照上面的操作就可以实现Slicing的功能。 但是, 对于一款像携程这样多子工程多业务线团队联合开发并上线多年的APP来说,大部分的图片都不是通过Asset Catalog的方式来管理的。APP里的已有图片大多是直接存储在普通的资源文件夹里。

所以,要想用Asset Catalog来自动实现Slicing的功能,首先能想到的是手动去迁移每个业务线bundle文件夹中的图片到Asset Catalog里去。 这样的做法可以实现目标,但是需要重复手动操作,除了拖拉图片到新建的Image Set里面,还需要手动对照图片名去给Image Set取名,繁冗且容易出错。

那么有没有自动化的的方法来实现App Slicing的功能呢?

答案是有的。如上图,在Xcode里,选中Application的target,然后选中Build Phases,可以看到一个Run Script的环节。 解决方案就是在编译后期, 通过Script来模拟实现Asset Catalog的图片管理功能,打包所有的图片资源文件并生成特殊的Assets.car文件夹。

用Script来实现App Slicing

首先, 让我们来查看一下用Asset Catalog来管理的图片资源的文件结构。

上文中举过一个通过Asset Catalog添加一个Oval图片的例子。 如上图, 在Finder里打开Images.xcassets, 可以看到在Xcode里新添加的每一个Image Set里都有对应的 .imageset 文件夹。 在该文件夹里, 有着在Xcode里通过Asset Catalog添加的一张图片的不同分辨率的资源。 除此以外, 还有一个名为Contents.json的文件。

如上图,Contents.json里储存的是一些key-value pair的资源内容信息。”images”对应的是一个数组的不同分辨率的图片信息。这些信息包括:idiom – 设备家族, scale – 分辨率, filename:图片文件名。 其中,idiom信息的记录为可选。 “info”对应的是版本信息和文件作者。

要想去模拟实现Asset Catalog的图片管理方式,就要在Build Phases里用Script对于每一张图片资源去生成这样的一个文件结构以及Contents.json文件, 等同于每张图片资源是通过Asset Catalog来添加和管理的一样,如下图。

实现在了这样的Images.xcassets文件结构和内容以后,等于完成了一大半的工作量。 前文中还提到,运用了Slicing功能的APP,会在ipa文件把所有的图片资源压缩并统一储存在一个名为Assets.car的特殊文件夹里。 苹果应用商城通过对上传的ipa文件里的Assets.car检验处理,才会自动去生成并下发针对不同设备适配的不同App安装包。 所以,还剩一步就是去把Images.xcassets转化成Assets.car。

前文中提到过Assets.car不是一个普通的文件夹。 实际上, 它是Asset Catalog管理的图片资源在编译后得到的版本。要想在Run Script Phase生成Assets.car, 需要用到Command Line Tools命令行中的actool工具。

actool应该存在于/Applications/Xcode.app/Contents/Developer/usr/bin/目录下。如果发现该目录下没有actool。可以执行下图中的命令,之后会弹出一个对话框,点击安装即可。

在有了actool之后,编译Images.xcassets从而生成Assets.car就只需要执行一条命令。

如上图,有两点要说明。 需要把${wdir}替换成编译过程中Images.xcassets的父文件夹地址,而--minimum-deployment-target需要填7.1或者以上。将这条命令执行好以后, ${wdir}目录下便会有全新的Assets.car生成。

综上所述,在Build Phases的Run Script环节用Script去实现模实现Asset Catalog图片管理方式并生成Assets.car文件以后,APP Slicing的功能就基本实现了。

如上图, 在iOS application archive打包完成之后,开发者可以通过核实针对各个iOS设备生成的ipa包的大小,来验证App Slicing带来的效果。 记住一点,拥有Slicing功能的App在发布到苹果商城供用户下载时, 不同iOS设备下载的安装包都是经过优化的。Assets.car里面的不同分辨率的同一张图会适配到不同的iOS设备的安装包中,以此实现缩小app size的功能。

4. App Slicing过程中碰到的问题和注意点

App Slicing是基于Asset Catalog管理图片功能之上的。Asset Catalog管理的图片的读取方式是 [UIImage imageNamed:@"imageName"]。 然而,iOS工程中普遍存在的另一种图片的读取方式是[UIImage imageWithContentsOfFile:@"imagePath"], Asset Catalog管理的图片是无法通过imagePath图片路径来读取的。 所以对于这种场景, 需要去有意识地选择是否使用Asset Catalog, 毕竟两种图片的读取方式对于在内存的占用影响都不同。

除此以外,对于Script的维护也会成为日常的工作。新增图片和已有图片的迁移改动,都可能会需要去对Script做修改。

最后,上文也提到过App Slicing是iOS 9新推出的功能, 它仅对iOS系统是9.0.2及以上版本设备有效。

5. 参考资源

  • Reducing the size of my App

https://developer.apple.com/library/content/qa/qa1795/_index.html

  • iOS App Thinning

https://developer.apple.com/library/content/documentation/IDEs/Conceptual/AppDistributionGuide/AppThinning/AppThinning.html

  • actool man page

https://developer.apple.com/legacy/library/documentation/Darwin/Reference/ManPages/man1/actool.1.html

0 人点赞