iPhone经过这几年的发展,已经发生了很大的变化,例如屏幕变得更加多样,尺寸更多,内存变得更大,CPU的架构也在变化。伴随着iPhone的变化,iOS也在变化,例如AutoLayout、size classes、split view controller等。这些技术及设备的变化给我在开发的过程中也造成了许多的问题,不仅如此苹果通过不断推出新的技术,努力在帮助我们使用同一套代码开发适应多个设备的Universal的App。另一方面Universal App虽然在开发的过程中,方便了我们开发人员,可是对于用户来说就不那么友好了,由于需要适配多种设备,所以里包含所有设备的代码,但真正的在运行的时候,我们并不需要那么多相关的代码及资源。

例如下面的一张图,是一个App运行在iPhone 6+上,使用的各个资源相关的情况: 

上图中对勾标出来的是在iPhone 6+上真实运行的时候使用到的相关的资源及代码,对比有对勾的部分,更多的是没有被对勾标出来的部分。可以想象我们下载了一个App(前提这个App是Universal的),然后至少一半的代码及资源是我们不需要的,白白占用着我们的空间。这样对用户体验也不好。为了解决这个问题苹果在iOS 9给出了新的解决方案:

  • App Slicing 当你提交你的iOS 9 打包文件到App Store的时候,苹果编译你的资源和可执行文件,然后为每个设备生成一个特定的可执行文件。最终,设备只会下载适应与其特性的,并且它使用到的内容。这些特性包含显卡性能(原文单词:graphics capabilities)、内存级别、CPU架构、size classes、屏幕 scaling等。
  • On Demand Resouces 应用程序的资源只有在需要使用的时候才会下载,并且如果其他资源需要空间这些资源可以被移除。
  • Bitcode 在你提交App到App Store的时候,Bitcode可以作为中间产物一起提交。包含bitcode配置的程序将会在App store上被编译和链接。bitcode允许苹果在后期重新优化我们程序的二进制文件,而不需要我们重新提交一个新的版本到App store上。

这三个技术加起来,统一称为App Thinning。

Getting started

打开本章节的初始项目,然后选在iPad Air 2运行,这时候运行效果如下: 

伴随着模拟器启动起来的还打开了一个Finder窗口: 

这个Finder窗口能够打开,是因为在程序中添加了一个脚本,每次运行的时候都会执行,脚本所在地方如下: 

echo "App Size in KB:  `du -sk \"${CONFIGURATION_BUILD_DIR}/${EXECUTABLE_NAME}.app\"`"
if [ "${CONFIGURATION}" = "Debug" ]; then
open ${CONFIGURATION_BUILD_DIR}
fi
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

在Finder的Old CA Maps点击右键,选择显示包内容,如下: 

上图中标注的说明如下: 
1. Assets.car是Assets.xcassets被Xcode进行编译后的文件。 
2. Old CA Maps是真实运行在设备上的可执行文件。 
3. Santa Cruz PNGs 这个是图片文件,但是没有被编译到Assets.car文件中,这是因为它并没有放到Assets.xcassets中,而是放到了工程的顶层文件中。 
4. SD_Map.bundle 这个就是地图图片文件,但是将近120MB。

Measuring your work

本章介绍一些App瘦身相关的东西,所以我们必须能够测量App是否减少了。工程里面已经内置了一个脚本(上面代码里面有),能够在build的过程中输出App的大小。查看的位置如下: 

Slicing up app slicing

App slicing包含两部分内容:可执行文件分片(Executable slicing)和资源分片(resource slicing)。

Executable slicing 指的是在设备下载App的时候会根据设备的相关信息只是下载对应该设备的相关的可执行文件,并不会包含其他设备及架构的可执行文件,达到App安装包的缩小。并且这个功能并不需要我们做太多,App Store默认支持的。

默认情况下提交到App Store的包是包含所有的内容的,这些都在配置文件里面,App Store会自动创建对应于每个类型的可执行文件。这个在iOS9+上支持。

Being smart with resources

Resource slicing 需要我们一小部分简单的工作就能实现。如果使用Resource slicing,则要保证我们的资源都被Asset Catalogs管理。在Xcode 7中,能够标记资源被使用设备的 Memory 和 Graphics ,如下: 

Your first fix

在开始的时候介绍过Santa Cruz PNGs这个文件因为被放到Main bundle中,所以不能被编译进入到Assets.car,进而也不能使用Resource slicing。下面看一下我们怎么修改,使其能够使用: 

选择New Image Set后,将新加入的set命名为Santa Cruz,紧接着做如下操作: 

纠正一下 上图左边的内容应该是删除,包括在Finder内也应该删除

然后在不同的设备上运行App,最后发现Asset.car文件的大小并不一致。这个是因为在安装的时候,会根据设备安装对应的资源。

Lazily (down)loading content

苹果提供On-Demand Resources技术,简称ODR。ODR允许你将资源存储在苹果的服务器上,然后在你App使用的时候再去下载。NSBundleResourceRequest是处理ODR的类,使用这个类能够通过tag下载对应的资源。images, data, OpenGL shaders, SpriteKit Particles, Watchkit Complications等都可以使用ODR。

Wire things up to use tags

下面我们修改代码,实现资源的下载,修改MapChromeViewController.Swift对应方法如下:

  private func downloadAndDisplayMapOverlay() {
// displayOverlayFromBundle(NSBundle.mainBundle())
guard let bundleTitle = mapOverlayData?.bundleTitle else {
return
} let bundleResource = NSBundleResourceRequest(tags: [bundleTitle]) bundleResource.beginAccessingResourcesWithCompletionHandler { [weak self] (error) -> Void in
NSOperationQueue.mainQueue().addOperationWithBlock({ () -> Void in
if error == nil {
self?.displayOverlayFromBundle(bundleResource.bundle)
}
})
} }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

这时候我们运行代码,可能会在控制台输出错误,这是因为我们对应的bundle并没有tag,我们需要给bundle添加tag: 

然后我们重新编译运行我们的程序,然后按照上面的查看编译运行的程序的大小,发现小了许多。对比之前的编译生成的文件,发现运行文件里面不包含bundle了。 

如果你的App在App Store上可能这个资源文件下载的很慢。但是在开发的过程中,Xcode会利用本地网络作为服务器,然后在设备上能够下载到,所以在开发的过程中如果电脑关了,那ODR也就不能使用了。

Make it download faster

在我们使用ODR的过程中,如果bundle比较大,可能再下载的过程中就会比较耗时,并且在下载过程中用户不知道,这样用户体验就不好。我们可以再Resource下载的过程中给用户一些提示,修改下面的代码:

// add 为新添加的 ProgressView是程序已经添加上的
private func downloadAndDisplayMapOverlay() {
// displayOverlayFromBundle(NSBundle.mainBundle())
guard let bundleTitle = mapOverlayData?.bundleTitle else {
return
} let bundleResource = NSBundleResourceRequest(tags: [bundleTitle]) bundleResource.loadingPriority = NSBundleResourceRequestLoadingPriorityUrgent //add loadingProgressView.observedProgress = bundleResource.progress // add loadingProgressView.hidden = false // add
UIApplication.sharedApplication().networkActivityIndicatorVisible = true // add bundleResource.beginAccessingResourcesWithCompletionHandler { [weak self] (error) -> Void in
NSOperationQueue.mainQueue().addOperationWithBlock({ () -> Void in
self?.loadingProgressView.hidden = true // add
UIApplication.sharedApplication().networkActivityIndicatorVisible = false // add
if error == nil {
self?.displayOverlayFromBundle(bundleResource.bundle)
}
})
} }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

如果用户已经下载过某个bundle,下次在使用的时候就不会再去下载了。

The many flavors of tagging

虽然添加了ProgressView,在体验是好了一点,但是需要注意测试的时候是使用的本地的网络,所以比较快,但是如果要是提交到App Store上,那可能下载就是比较慢了,如果再配上用户没有WiFi那可能就没法用了,所以我们还需要做其他的一些调整。

Initial install tags

使用Initial install tags,我们可以设置哪些bundle会在我们App初始化安装的时候就会被下载。 下面下介绍一下ODR三种下载的时机吧: 
Initial Install Tags 在ipa下载的时候一同下载 
Prefetched Tag Order 在程序下载完成后,下载对应的资源,然后按顺序排列。 
Prefetched Tag Order 按需下载 
下面是配置的地方: 

Purging content

应用程序在使用的过程中通过ODR下载了对应的bundle,但是有时候我们需要清理一些已经下载过的并且不使用的bundle。在介绍怎么删除之前先看一下怎么查看下载的ODR: 

Set a resource to be purged

在MapChromeViewController.swift添加如下代码:

  // new add 是新加的代码
var overlayBundleResource: NSBundleResourceRequest? // new add
private func downloadAndDisplayMapOverlay() {
// displayOverlayFromBundle(NSBundle.mainBundle())
guard let bundleTitle = mapOverlayData?.bundleTitle else {
return
} let bundleResource = NSBundleResourceRequest(tags: [bundleTitle])
overlayBundleResource = bundleResource // new add bundleResource.loadingPriority = NSBundleResourceRequestLoadingPriorityUrgent //add loadingProgressView.observedProgress = bundleResource.progress // add loadingProgressView.hidden = false // add
UIApplication.sharedApplication().networkActivityIndicatorVisible = true // add bundleResource.beginAccessingResourcesWithCompletionHandler { [weak self] (error) -> Void in
NSOperationQueue.mainQueue().addOperationWithBlock({ () -> Void in
self?.loadingProgressView.hidden = true // add
UIApplication.sharedApplication().networkActivityIndicatorVisible = false // add
if error == nil {
self?.displayOverlayFromBundle(bundleResource.bundle)
}
})
} } // new add
override func viewDidDisappear(animated: Bool) {
super.viewDidDisappear(animated)
// 告诉系统结束了对资源的访问
overlayBundleResource?.endAccessingResources()
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

上面的代码,我做测试的时候不清楚会在什么时候会删除,我也模拟了内存警告,如果谁清楚,还请告诉我,谢谢。

坚持了好几天中午写完了,这篇笔记,一篇笔记13张截图,好累。

【转】app瘦身的更多相关文章

  1. iOS - Bitcode App 瘦身中间码

    1.Bitcode 随着 Xcode7 的发布,Apple 提供了一项新的技术来支持 App 瘦身功能,那就是 Bitcode. 1.BitCode 是什么 Bitcode is an interme ...

  2. App瘦身、性能优化总结

    App瘦身 资源瘦身 使用tinypng压缩PNG图片.视频可以通过 Final cut等软件进行分辨率压缩.音频则降低码率即可. 非必须资源文件可以放到自己服务器上 启动图使用 LaunchScre ...

  3. 包建强的培训课程(6):Android App瘦身优化

    v\:* {behavior:url(#default#VML);} o\:* {behavior:url(#default#VML);} w\:* {behavior:url(#default#VM ...

  4. app瘦身和包压缩技术有什么区别?

    APP瘦身 针对app文件中的文件进行优化,利用素材的拉伸,祛除不必要的文件,优化png, jpg素材,压缩音视频素材等方式实现app文件的减小. 包压缩技术 所谓包压缩,顾名思义就是将手游的安装包体 ...

  5. 如何实现手游app瘦身?

    手游服务商来说,手游包体大一直是个很困扰的问题.一款手游产品而言,包体大小和更新方式对于有效用户的转化率往往起到非常关键的作用,话说手游安装包越小,用户转化率越高,那该如何实现app瘦身呢? 工具/原 ...

  6. iOS App 瘦身方案

    缩减iOS安装包大小是很多中大型APP都要做的事,一般首先会对资源文件下手,压缩图片/音频,去除不必要的资源.这些资源优化做完后,我们还可以尝试对可执行文件进行瘦身,项目越大,可执行文件占用的体积越大 ...

  7. APP瘦身绝技(快速减少包大小)

    如果要清理无用类文件和无用图片,参考博客<iOS 清理Xcode项目中没有使用到的图片资源和类文件>.当下众多app项目,尤其是初创公司,明显的特点就是,开发周期短,迭代更新快,甚至一周一 ...

  8. App瘦身

    http://www.zoomfeng.com/blog/ipa-size-thin.html https://github.com/ming1016/SMCheckProject

  9. IOS APP 瘦身

    只保留其中一宗编译环境包 lipo -thin armv7 XXAPP -output XXAPP.armv7

随机推荐

  1. 【USACO 1.3.3】回文串

    [題目描述] 据说如果你给无限只母牛和无限台巨型便携式电脑(有非常大的键盘),那么母牛们会制造出世上最棒的回文.你的工作就是去寻找这些牛制造的奇观(最棒的回文). 在寻找回文时不用理睬那些标点符号.空 ...

  2. iscroll.js & flipsnap.js

    两个js都可以用做手机的滑动框架iscroll.js功能更多flipsnap.js应该只能水平滑动. iscroll.js介绍http://iiunknown.gitbooks.io/iscroll- ...

  3. CentOS 6.5下安装MySql 5.7

    不管您按下面的方法安装成功否,请留个言,把您遇到的问题写上共勉! 包下载http://url.cn/WrNg5S 环境: 1).软硬件:E6420双核CPU,8G内存,1T硬盘 2).虚拟机下 Cen ...

  4. Python datetime time 常用操作

    测试版本: Python 2.7 获取当前时间的两种方法 import datetime,time now = time.strftime("%Y-%m-%d %H:%M:%S") ...

  5. Linq介绍

    什么是LINQ? LINQ全称Language Integrated Query,中文翻译"语言集成查询".在.NET框架中,大致使用三大组件实现这个封装,分别 LINQ to O ...

  6. 19 Remove Nth Node From End of List(去掉链表中倒数第n个节点Easy)

    题目意思:去掉链表中倒数第n个节点 思路:1.两次遍历,没什么技术含量,第一次遍历计算长度,第二次遍历找到倒数第k个,代码不写了   2.一次遍历,两个指针,用指针间的距离去计算. ps:特别注意删掉 ...

  7. text-overflow:ellipsis 的应用(转载)

    关键字: text-overflow:ellipsis 语法:text-overflow : clip | ellipsis 取值: clip :默认值 .不显示省略标记(...),而是简单的裁切. ...

  8. Access数据库导入到mysql数据库中

    做项目时需要查询手机号归属地的,用网上提供的接口,耗时太长,反应慢,只能自己在网上搜了一个包含所有手机号归属地的Access数据库,导入到自己的mysql数据库中 Access数据库导入到mysql中 ...

  9. python numpy 使用笔记 矩阵操作

    (原创文章转载请标注来源) 在学习机器学习的过程中经常会用到矩阵,那么使用numpy扩展包将是不二的选择 建议在平Python中用多维数组(array)代替矩阵(matrix) 入门请考 http:/ ...

  10. CentOS 7 安装tomcat

    1.下载Linux版的tomcat 2.上传下载tomcat文件到/usr/local中执行以下操作 [root@admin local]# cd /usr/local [root@admin loc ...