介绍
除了iOS 9和watchOS 2,Apple还引入了按需资源,这是一个用于向您的应用程序交付内容的新API,同时还减少了该应用程序在用户设备上占用的空间。 使用按需资源,您可以标记应用程序的特定资产,将其托管在Apple的服务器上,以便用户在需要时可以下载它们。 在本教程中,我将通过创建一个基本的图像查看器应用程序向您展示点播资源的基础知识。
先决条件
本教程要求您正在运行Xcode 7+,并且熟悉iOS开发。 您还需要下载入门项目GitHub 。
1.按需资源
好处
iOS 9和watchOS 2中引入了按需资源,其主要目的是减少单个应用程序在设备上占用的空间量。 按需资源的另一个重要优势是用户可以更快地下载和打开您的应用程序。
按需资源的工作原理是,为Xcode中的资源分配唯一的标记 ,以创建所谓的资产包 。 这些包可以包括资产目录中的任何内容(图像,SpriteKit纹理,数据等),甚至可以包括其他文件,例如OpenGL和Metal着色器以及SpriteKit和SceneKit场景和粒子系统。
当您将应用程序提交到App Store时,这些资源也将被上传并托管在那里,以便随时下载。 要在运行时在应用程序中下载资产包,只需对在Xcode中分配的每个包使用标签。
分类目录
使用按需资源的应用程序的两个主要方面是应用程序捆绑包 ,其中包含用于您的应用程序和基本资产的可执行代码,例如用户界面图标和资产包 。
对于这些资产包,可以在Xcode中组织三个主要类别:
- 初始安装:用于首次运行您的应用所需的内容,但以后可以删除。 这可能包括游戏的前几个级别,一旦玩家深入游戏就不再需要这些级别。
- Prefetched(预取):此类别包括您想要在应用程序完成安装后立即下载的内容。 建议将此类内容用于应用程序在安装后无需功能即可使用的资源,但这些资源是获得更好用户体验所必需的。 一个很好的例子是游戏教程。
- 随需应变:此类别针对以后需要的内容,而您的应用程序可以不运行而运行。 使用按需资源时,这是您将使用的最常见的类别类型。
限度
支持按需资源构建的应用程序还必须遵守以下文件大小限制:
- 2 GB用于iOS应用程序捆绑包
- 2 GB用于基本安装标签
- 2GB用于预取标签
- 2GB用于使用中的资源。 这仅在您的应用程序正在运行并使用按需资源时才重要。
- 每个单独的资产包512MB 。 单个标签不能包含超过此数量的数据。 如果超过此限制,Xcode会警告您,并允许您仍然测试和开发应用。 但是,任何提交到App Store的尝试都将失败。
- Apple托管的所有资源20 GB 。 这是您的应用程序随时可以下载的资源总量。 虽然一次只能使用2GB,但如果用户的设备有足够的存储空间,则可以随时下载多达20GB的资源并使之可访问您的应用程序。
应用切片
请注意,总计20GB不会占应用程序切片的数量,而其他所有总计会占比例。 什么是应用切片? 应用程序切片是iOS 9中引入的另一个功能,可以减少应用程序的大小。 它仅通过查看特定于安装该应用程序的设备的资源来执行此操作。 例如,如果正确使用了资产目录,那么安装在iPhone 6 Plus或6s Plus上的应用程序只需要下载3x比例的图像,而不必担心1x和2x比例。 对于按需资源,可以上载到App Store服务器的20GB总资源是所有设备类型的总资源。 所有其他限制均针对要在其上安装应用的每个特定设备。
删除按需资源
在数据删除(清除)方面,只有在安装了应用程序的设备的可用空间不足时,才会删除应用程序下载的资产包。 发生这种情况时,按需资源系统将查看设备上的所有应用程序,选择后将查看每个资产包的保存属性以及上次使用的时间。 需要注意的重要一件事是,在您的应用程序运行时,永远不会清除该应用程序的资产包。
2.分配和组织标签
在Xcode中打开starter项目,然后在iOS Simulator中运行该应用程序。 目前,该基本应用程序包含一组图像,每种图像都具有三种颜色(红色,绿色或蓝色)之一和四种形状(圆形,正方形,星形或六边形)之一的组合。 运行该应用程序后,导航至“ 颜色”>“红色” ,您将在屏幕上看到一个红色圆圈图像。
![应用菜单](https://i-blog.csdnimg.cn/blog_migrate/ee13141186ff6fbb9db70c8294b8c439.png)
![颜色菜单](https://i-blog.csdnimg.cn/blog_migrate/43a1619971ae8dbb0c00d3fbf4904f7f.png)
![红圈](https://cms-assets.tutsplus.com/uploads/users/855/posts/24929/image/Simulator%20Screen%20Shot%2027%20Sep%202015,%203.29.38%20PM.png)
在这个应用程序中,我们将总共设置七个资产包,每种颜色一套,每种形状一套。 按需资源的另一个重要功能是可以为一个资源分配多个标签。 例如,红色圆圈可以是红色资产包和圆形资产包的一部分。
按需资源API也足够聪明,不必两次下载或复制同一资源。 换句话说,如果应用程序已经下载了红色资产包,然后又想加载Circle资产包,则不会再次下载红色圆圈图像。
在Xcode中,打开Assets.xcassets 。 您应该看到所有十二个图像,如下所示。
![资产目录](https://cms-assets.tutsplus.com/uploads/users/855/posts/24929/image/Screen%20Shot%202015-09-27%20at%203.42.26%20PM.png)
接下来,选择“ 蓝色正方形”图像集并打开右侧的“ 属性”检查器 。
![属性检查器](https://i-blog.csdnimg.cn/blog_migrate/f046bf902e8c7e8614f846111b4afd4c.png)
您将看到Attributes Inspector包括一个新的On Demand Resource Tags部分,您可以在其中为每个资源分配标签。 对于蓝色正方形图像集,在“ 按需资源标签”字段中输入“ 蓝色”和“ 正方形 ”。 这意味着图像集现在已分配了两个标签。
![蓝色广场标签](https://i-blog.csdnimg.cn/blog_migrate/bc258afec4cd43c81e73a2f33939546e.png)
请注意,入门项目已经包含了十二个图像集中的九个的资源标签。 这就解释了为什么Xcode在您输入这些标记时为您提供自动完成选项。
完成为“ 蓝色正方形”图像集分配标签后,将正确的标签添加到两个 绿色六角形和红色圆圈图像集如下所示。
![绿色六角形标签](https://i-blog.csdnimg.cn/blog_migrate/3999f27a17e7186bb993ffd85295ca77.png)
![红色圆圈标签](https://i-blog.csdnimg.cn/blog_migrate/30ddd7028bb64c30c727680733f77740.png)
正确设置按需资源标签后,打开左侧的项目浏览器 。 打开顶部的“ 资源标签”选项卡,然后在顶部选择“ 预取”过滤器。
![标签概述](https://i-blog.csdnimg.cn/blog_migrate/a41a0c9de954e7798108193b2ad90488.png)
现在,您可以看到每个资产包的大小以及每个资产包中的确切资源。 “ 全部”过滤器将显示每个按需资源。 Prefetched过滤器显示每个类别的按需资源,它使您可以将资源从一个类别移动到另一个类别:
- 初始安装标签
- 预取标签顺序
- 仅按需下载
这些部分反映了我之前概述的资产包的三个类别。 需要注意的重要一件事是,您在“ 预购标签订单”部分中放入的资产包将按照它们出现的顺序开始下载。
通过将标签分配给每个图像集,是时候开始访问项目中的资源了。
3.按需访问资源
通过新的NSBundleResourceRequest
类处理访问App Store服务器上托管的资产包。 使用要使用的一组标记创建此类的实例。 它告诉系统您使用相应资产包的情况。 这些NSBundleResourceRequest
对象的解除分配是告诉操作系统何时不再使用特定资产包的最佳和最简便的方法。 这很重要,这样您就不会超过2GB的使用资源限制。
在您的项目中,打开DetailViewController.swift并将以下属性添加到DetailViewController
类。
var request: NSBundleResourceRequest!
接下来,将您的viewDidAppear(_:)
方法替换为以下内容:
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
request = NSBundleResourceRequest(tags: [tagToLoad])
request.beginAccessingResourcesWithCompletionHandler { (error: NSError?) -> Void in
// Called on background thread
if error == nil {
NSOperationQueue.mainQueue().addOperationWithBlock({ () -> Void in
self.displayImages()
})
}
}
}
使用此代码,您首先要使用包含单个标签的集合初始化request
属性。 您提供给此初始值设定项的标记集包含字符串值。 在这种情况下,我们使用tagToLoad
属性,该属性由应用程序中的先前视图控制器设置。
接下来,我们通过调用beginAccessingResourcesWithCompletionHandler(_:)
开始下载指定标签的资产包。 此方法将访问具有指定标签的所有资源,并在需要时自动开始下载。 以这种方式访问资源后,用于将这些资源加载到应用程序中的所有其他代码都保持不变。
请注意,如果只希望访问已下载的资源而不加载内容,则可以使用conditionallyBeginAccessingResourcesWithCompletionHandler(_:)
方法。
如上面的代码所示,关于此完成处理程序,要记住的重要一件事是在后台线程上调用它。 这意味着您想要在完成时进行的任何用户界面更新都需要在主线程上执行。
再次构建并运行您的应用,然后选择一种颜色或形状以在应用中查看。 您应该看到所有三个彩色图像的特定形状或所有四个形状的特定颜色。
![显示所有资源](https://i-blog.csdnimg.cn/blog_migrate/f9d5387bce95bf759c61ccb9919cd660.png)
这就是使用按需资源的简单程度。 现在,您已成功在应用程序中实现了按需资源。
Xcode 7中提供的重要调试功能是能够查看已下载的资产包以及正在使用的资产包。 要查看此内容,请在运行应用程序的情况下导航至Debug Navigator ,然后选择Disk 。 您将看到类似于以下所示的屏幕。 按需资源是我们感兴趣的部分。
![按需资源调试](https://i-blog.csdnimg.cn/blog_migrate/90bdddcbf84f4905742d877ac0de1e9d.png)
作为示例,现在让我们更改下载优先级,以便始终可以立即下载某些资源。 同时,我们将更改资产包的保存优先级,以便在“ 圆形”和“ 方形”资产包之前清除六角形和星形资产包。 如下所示更新viewDidAppear(_:)
方法的实现。
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
request = NSBundleResourceRequest(tags: [tagToLoad])
request.loadingPriority = NSBundleResourceRequestLoadingPriorityUrgent
NSBundle.mainBundle().setPreservationPriority(1.0, forTags: ["Circle", "Square"])
NSBundle.mainBundle().setPreservationPriority(0.5, forTags: ["Hexagon", "Star"])
request.beginAccessingResourcesWithCompletionHandler { (error: NSError?) -> Void in
// Called on background thread
if error == nil {
NSOperationQueue.mainQueue().addOperationWithBlock({ () -> Void in
self.displayImages()
})
}
}
}
初始化请求后,将loadingPriority
属性设置为NSBundleResourceRequestLoadingPriorityUrgent
。 另外,您可以给此属性分配0.0到1.0之间的任何数字,以规定应用程序内的加载优先级。
使用此常量的优点是,它会自动为请求提供最高的加载优先级,但同时也会忽略当前的CPU活动。 在某些情况下,如果设备的CPU使用率很高,则资产包的下载可能会延迟。
接下来,我们为所有四个形状标签设置保存优先级。 这是通过调用应用程序的主捆绑包的setPreservationPriority(_:forTags:)
方法来完成的。 现在,我们确保,如果按需资源系统需要从我们的应用程序中清除某些资产,则将首先删除Hexagon和Star资产包。
4.最佳做法
既然您知道如何在iOS应用程序中实现按需资源,那么我想简要地告诉您一些牢记的最佳实践。
保持单个标签尽可能小
除了减少下载时间并使资源更易于访问之外,将每个资产包保持尽可能小还可以防止系统过度清洗。 这是按需资源系统需要释放一定数量的空间并最终释放出比所需更多的空间的时候。
例如,如果系统需要释放50MB的空间,并且根据前面提到的条件,确定最适合删除应用程序中的400MB资产包,则系统将清除350MB以上的空间。 这意味着,如果您的应用丢失的数据超过了需要的数量,它将需要再次下载与该标签关联的所有资源。 单个标签的建议大小约为64MB。
提前下载标签
如果您的应用程序具有非常可预测的用户交互,那么最好在实际需要它们之前开始下载资源。 这是为了改善用户的体验,因为在您的应用下载内容时,他们不必盯着加载屏幕。
游戏是一个常见的例子。 如果玩家刚刚完成第5级,那么最好在她玩第6级时开始下载第7级。
停止正确访问资源
完成使用特定资产包的操作后,请确保已释放NSBundleResourceRequest
对象,或者在其上调用endAccessingResources
方法。
这不仅可以避免您的应用程序使用中的资源达到2GB的限制,还可以帮助按需资源系统知道您的应用程序何时使用这些资源,这意味着它可以更好地决定如果有更多空间可以清除什么内容。需要。
5. tvOS的按需资源
我最近写了有关tvOS开发的文章 ,在该教程中,我提到了tvOS应用程序的局限性。 一个应用程序捆绑包的最大大小为200MB,因此强烈建议您尽可能使用tvOS应用程序中的按需资源。
由于tvOS和iOS的相似性,按需资源的API和存储限制(应用程序捆绑除外)是相同的。 但是,在tvOS上使用按需资源时,记住所有资产(例如图像)具有单个1x缩放版本也很重要,因此,由于应用程序切片,Xcode中显示的资产包的大小不会减小。
结论
iOS 9和tvOS中的按需资源是减少应用程序大小并为下载和使用应用程序的人提供更好的用户体验的好方法。 尽管很容易实现和设置,但您必须牢记许多细节,以使整个按需资源系统能够完美地工作,而不会导致过多的加载时间和不必要的数据清除。
与往常一样,请务必在下面的评论中留下您的评论和反馈。