转载

iOS 9 by Tutorials 笔记(四)

App Thinning

Apple 已经推出了很多种尺寸的 iPhone 了,从 iOS 方面,苹果也一直努力地消除这种硬件多元化给开发者带来的困扰,如 iOS 8 推出了 Adaptive Layout , Trait Collections , Universal split view controllers ,从此你不再需要为某个特定的设备开发独占 App,而是开发一个通用 App 适配所有设备。

然而这也带来一些挑战,因为要包含所有设备的资源文件,这个通用的 App 所占空间容量都比较大。所以 iOS 9 拿出了新的解决方案:

  • App Slicing 当你将 iOS 9 打包的二进制文件提交到 App Store,Apple 会编译然后为每个特定的设备单独形成一个可执行文件,这样设备真正从商店下载的时候,只会根据特定的设备来下载安装,削减了尺寸。
  • On Demand Resources 应用资源可以在仅被需要时才下载
  • Bitcode bitcode是被编译程序的一种中间形式的代码。包含bitcode配置的程序将会在App store上被编译和链接。bitcode允许苹果在后期重新优化我们程序的二进制文件,而不需要我们重新提交一个新的版本到App store上。

以上这三种技术加起来被称为 App Thinning

Measuring your work

我们可以通过这种方式来对 App 瘦身过程进行量化

iOS 9 by Tutorials 笔记(四)

Slicing up app slicing

App slicing 可分为两部分: executable slicingresource slicingExecutable slicing 就是 Apple 将根据不同的设备安装特定的 App,你不需要做太多事情,Apple 已经为你做好了一切。

Being smart with resources

Resource slicing要求你做的事情也很简单,将所有的资源文件放到 Asset Catalogs 下,并且按照相关特性进行组织,从 Xcode 7 开始,你可以根据 Memory 和 Graphics 来标记资源文件了

iOS 9 by Tutorials 笔记(四)

Lazily (down)loading content

现在我们通过对资源的『按需使用』来削减内容尺寸(俗称 ODR),ODR 允许你将资源存储在 Apple 的服务器上,之后仅在需要时才会下载使用。

NSBundleResourceRequest 负责处理 ODR,通过这个类,可以通过 Tags 来控制内容的下载。对 tags 的使用,Apple 模糊了本地资源和远程资源的界限。

使用 ODR 可以包括 images,data,OpenGL shaders,SpriteKit Particles,Watchkit Complications 等

针对 NSBundles 可看做是 data 文件,因此对于 ODR 来说也是支持的。

Wire things up to use tags

现在是代码时间,将之前的本地载入资源文件( NSBundles 文件)改为远程异步载入,修改 downloadAndDisplayMapOverlay() 方法

// 1 guard let bundleTitle =     mapOverlayData?.bundleTitle else { return   } // 2 let bundleResource =   NSBundleResourceRequest(tags: [bundleTitle])   // 3 bundleResource.beginAccessingResourcesWithCompletionHandler {     [weak self] error in // 4   NSOperationQueue.mainQueue().addOperationWithBlock({ // 5     if error == nil {       self?.displayOverlayFromBundle(bundleResource.bundle)     }   })  } 

beginAccessingResourcesWithCompletionHandler(_:) 会在完成 on-demand 内容下载后,调用 completion block 将资源文件显示到屏幕上。

How about those tags

现在我们完成最后一步: 标记 tags

  1. 选中我们要标记的资源文件(LA_Map.bundle)
  2. 在 File Inspector 中找到 On Demand Resource Tags 部分
  3. 填写相应的 Tags

iOS 9 by Tutorials 笔记(四)

现在运行程序,选中 LA(LA_Map.bundle 被标记过,所以会被存储在云端),此时将从 Apple 的服务器上下载相应的资源文件

Make it download faster

LA 这个 bundle 相对来说还比较小,如果你尝试下 San Diego,会发现花很长时间来下载

对于已经通过 ODR 加载过的资源文件,再次显示的时候,ODR 会缓存来保证速度,除非触发了清空条件,否则将会一直缓存这些资源文件

为了避免应用被评为一星,你可以加一个进度条来告诉用户你的 app 正在下载内容,同样是回到 downloadAndDisplayMapOverlay() 方法

guard let bundleTitle =     mapOverlayData?.bundleTitle else {   return } let bundleResource     = NSBundleResourceRequest(tags: [bundleTitle]) // 1 bundleResource.loadingPriority     = NSBundleResourceRequestLoadingPriorityUrgent // 2 loadingProgressView.observedProgress     = bundleResource.progress // 3 loadingProgressView.hidden = false   UIApplication.sharedApplication()     .networkActivityIndicatorVisible = true  bundleResource.beginAccessingResourcesWithCompletionHandler {     [weak self] error in   NSOperationQueue.mainQueue().addOperationWithBlock({ // 4     self?.loadingProgressView.hidden = true     UIApplication.sharedApplication()       .networkActivityIndicatorVisible = false     if error == nil {       self?.displayOverlayFromBundle(bundleResource.bundle)     }   })  } 

loadingProgressView 将会随下载进度进行实时更新

The many flavors of tagging

在真实世界,虽然你加上了进度条来做标记,但用户等待太长时间总归是件非常蛋疼的事情。因此你可以考虑将一些较大的资源文件设为初始数据打包进 IPA ,让他们一起下载安装

Initial install tags

选择工程名称 -> Target -> Resource Tags ,将 All 切换为 Prefetched ,会发现 ODR 有三种类型的处理方式:

  • Initial Install Tags :这个是资源文件随应用一起打包安装时使用,之后不需要时可以移除,所以也要由 ODR 来管理
  • Prefetched Tag Order :一旦完成下载,按顺序排列
  • Download Only On Demand :按需下载

现在我们可以根据需要,添加相应的资源文件

iOS 9 by Tutorials 笔记(四)

想要测试实际效果,需要提交到 TestFlight Beta Testing ,然后用真实设备下载测试即可。

Purging content

你可以帮助 iOS 系统在资源文件 不再需要时 从磁盘清除掉

Set a resource to be purged

  1. 设置一个 NSBundleResourceRequest 类型的属性 overlayBundleResource 用来标记下载到的资源文件

    var overlayBundleResource: NSBundleResourceRequest? 
  2. 将这个属性标记的指针指向获取到的资源文件,在资源文件下载显示方法 downloadAndDisplayMapOverlay() 中添加一条:

    overlayBundleResource = bundleResource 
  3. 最后在屏幕消失时告诉系统完成了对资源文件的访问

    override func viewDidDisappear(animated: Bool) {     super.viewDidDisappear(animated)     overlayBundleResource?.endAccessingResources() } 

具体的资源文件是否占用磁盘,可以通过下面的方式进行查看

iOS 9 by Tutorials 笔记(四)

-EOF-
正文到此结束
Loading...