AppThinning之AppSlicing

最近想给APP瘦身,号称包的大小也会影响用户量 = =, 所以立马去回顾一下WWDC 2015 Session 404,App Thinning in Xcode

AppThinning App由Slicing, On Demand Resources, Bitcode

Slicing

通过将app bundle资源根据不同的设备特性分为不同的版本。对于图片资源,会根据设备(如iphone6 plus需要@3x,iphone 6需要@2x)所需图片分辨率不同分发给对应设备所需对应的图片资源。

例如在6plus中,大屏储存需要3x的图片,所以会分发对应的图片资源

On Demand Resources

主要是加快下载速度,减小app的大小,改善第一次启动的体验。简而言之就是把资源放云端

Bitcode

是把指令集优化。根据你设备的状态去做编译优化,进而提升性能,对包的大小优化起不到什么本质上的作用


Slicing

苹果的文档如是说

In fact, app slicing handles the majority of the app thinning process. ‘App Slicing’ feature finally switched on in iOS 9.0.2

所以主要精力就放Slicing上吧

如何使用Slicing

对于Slicing的使用很简单只需要满足下面几个条件:

  • 当前项目的development target版本 iOS7及以上
  • 图片资源通过asset catalog进行管理
  • 设备版本必须是iOS9.0.2以后才会生效,以下的版本维持原样

APP通过asset catalog管理的图片在编译后,会在DPScope中生成Asset.car文件,该文件中包含了其管理的图片资源。App Slicing会对不同尺寸设备 编译之后的分发设备所需的@2x和@3x图片

在项目中现在图片主要分散在项目本身的Images.xcassets和各个业务Pod中, 针对现状如何使用Slicing有两种方案

  • 方案1

每个Pod单独建立各自的asset catalog,管理Pod自身的图片资源。这样在编译之后,会将项目中所有的asset catalog编译成一个Assets.car文件。
优点:每个pods单独管理自身的图片资源。
缺点:1.需要更改各个pod的podspec文件中的s.resource。指向该pod所建立的Asset.xcassets。2.不方便本地测试,只能通过发布到testflight测试。

  • 方案2

仍然通过App target中的Images.xcassets来管理整个项目中的图片资源。在pod install完毕后,将各个Pod中的图片资源放到Images.xcassets中来统一管理。(具体方法就是将图片拷贝到Images.xcassets中,生成对应图片名字的.imageset文件夹,文件夹下生成Contents.json文件来指定对应的1x,2x,3x版本图片用于分发)。
优点:各个pod不需要任何工作量
缺点:1.需要在pod install完毕后,删除Target Support Files中Pods-MyTarget-resources.sh中对应图片的 install_resource 行。不然编译会报错。2.通过脚本,在pod install完毕后,将Pods下的图片资源放到Images.xcassets中,并删除指定的shell脚本行数。

实际效果

设备类型 原始包大小 使用AppSlcing包大小 实际安装后大小
5s (@2x) 52.7M 35.4M 30.6M
6s plus(@3x) 52.7M 36.6M 31M

其他压缩图片减少包的方法

  1. tinypny压缩png图片
  2. 使用第三方工具image_optim压缩图片
  3. 使用xcode自带的pngcrush压缩图片

结论 2,3 然并卵 = =

踩过的坑

  1. 通过方案1进行调研的时候,虽然xcode会将项目中的xcassets和各个pod中的xcassets管理的图片打包成一个Asset.car文件,但是通过查看DerivedData中的Asset.car文件,发现图片并没有分发,最后发现原来是在pod install的时候,在Pods-MyTarget-resources.sh中影响了自动分发的功能,所以只能通过发布testflight来进行测试。测试发现,是能够自动分发图片的,只是本地无法测试。

  2. 通过方案2进行调研的时候,原以为只需要删除已经移除图片所对应的install_resource 行即可,但是发现仍有报错。一些的podspec中,对资源的使用通过s.resouce_bundle的形式使用的,而其余的pod的podspec对资源的使用是通过s.resouce形式引用的。所以在脚本中需要对上面的几个pod的图片暂时进行了剔除