本文翻译由唧唧歪歪翻译自Apple文档 On-Demand Resources Guide
On-Demand Resources Guide中文版(按需加载资源--下)包含管理按需加载资源、调试以及附录:资源类型

(一)按需加载资源基础

按需加载资源是由App Store托管的内容,它和下载的app bundle是分开的。app请求一系列按需加载资源,而下载和存储资源是由操作系统来管理。这些资源可以是除可执行代码外,bundle支持的任何类型。支持类型的完整列表,请参阅附录a:按需加载的资源类型。

按需加载资源主要可以带来以下的几种好处:

  • 初始资源的延迟加载。app有一些资源是主要功能要用到的,但在启动时并不需要。将这些资源标记为“初始需要”。操作系统在app启动时会自动下载这些资源。例如,图片编辑app有许多不常用的滤镜。

  • app资源的延迟加载。app有一些只在特定情景下使用的资源,当应用可能要进入这些场景时,会请求这些资源。例如,在一个有很多关卡的游戏中,用户只需要当前关卡和下一关卡的资源。

  • 不常用资源的远程存储。app有一些很少使用的资源,当需要这些资源时会去请求它们。例如,当app第一次打开时会展示一个教程,而这个教程之后就可能不会在用到。app在第一次启动时请求教程的资源,这之后只在需要展示教程或者添加了新功能才去请求该资源。

  • 应用内购买资源的远程存储。app提供包含额外资源的应用内购买。app会在启动完成后请求已购买模块的资源。例如,用户在一个键盘app内购买了SuperGeeky表情包。应用程序会在启动完成后请求表情包的资源。

  • 第一次启动时必需资源的加载。app有一些资源只在第一次启动时需要,之后的启动不再需要。例如,app有一个只在第一次启动时展示的教程。

在开发时,通过给按需加载资源分配一个或多个tag来区分。tag是一个你创建的字符串标识符。你可以使用tag的名称来区分这些资源在你的app中是如何使用的。例如,在一个游戏中,所有第五关的资源可以使用tag level-5。

在运行时,你通过指定tag来请求访问远程资源。操作系统会下载和这个tag关联的所有资源,然后保留在存储中,直到app不再使用它们。当操作系统需要更多的存储空间,它会清理一个或多个不再使用的tag关联的资源。tag关联的资源在被清理之前可能会在设备中保存一段时间。

继续上面游戏的例子,游戏有许多关卡,用户只需要当前正在玩的关卡和可能玩的下一关卡的资源。下图的上部展示了包括全部关卡资源的app bundle。可以通过为不同关卡和其他无需放在app内的资源,创建不同tag的按需加载资源,来缩减app bundle的大小。下图的底部显示了一个更小的app,其中加了tag的资源由App Store托管。

还有一些其他的功能,比如让你指定那些在app启动之前必须加载的资源,为资源请求设置优先级,追踪资源下载的进度,为不再使用的已下载tag设置保留优先级。

按需加载资源的生命周期

当用户第一次启动app时,设备上唯一的按需加载资源是那些设置为预获取的。随着用户使用app,app会请求加了tag的资源,使用这些资源,然后告诉操作系统不再使用这些资源了。在这之后的某个时间,操作系统会清理一个或多个tag。

注意:app应该请求tag,而不是单个资源。

当你在开发按需加载资源时,可能会注意到请求下载某个tag时,其他tag也会被下载。这是因为操作系统处理的是资源包(asset pack),这些资源包会为共享资源的下载进行优化。一个tag可能对应多个资源包。资源包是在构建app时由Xcode生成的。

加了tag的资源的生命周期如下所示:

1、加了tag的资源由App Store托管。

这发生在app第一次启动和之前加载的tag被清理时。

2、加tag的资源被下载到设备上

这发生在app请求一个设备上没有的tag之后,或者发生在操作系统下载初始资源。

下图中展示的是,app请求Level11和Foresttag关联的资源,然后下载到设备上。

3、操作系统将tag保存在本地存储中,并通知app这些tag已经可以使用。

这发生在一个tag下的所有资源都已成功下载之后,或者tag对应的资源都已缓存在本地存储中。

在tag可用之后,app就可以使用tag关联的资源了。按需加载资源的使用方式和使用下载的app中资源包一样。下图展示了下载的资源就像是app的虚拟成员一样。

4、操作系统释放本地存储中的tag。

被释放的tag还会保存在设备中,直到它再次被请求,或者从本地存储中被清理掉。当一个tag没有被任何请求持有时,tag就可以被清理。在tag被清理之前,它还可能在设备上保存一段时间,包括app多次启动。请求一个tag会持有该tag,然后返回上面的步骤3。

清理tag会返回到上面的步骤1。你可以为tag设置保存优先级来影响清理的顺序。更多信息参见管理按需加载资源。

启用按需加载资源

对于支持iOS 9.0及以后的app,按需加载资源是默认开启的。你也可以在target的build settings中手动更改。

启用或关闭按需加载资源:

  1. 在project navigator中选择工程文件。

  2. 在project editor中选择对应的target。

  3. 选择Build Settings选项卡。

  4. 展开Assets分类。

  5. 提示:可以在Build Settings选项卡右上角的搜索框中输入“Assets”,来快速定位到Assets分类。

  6. 设置Enable On-Demand Resources的值。

  7. Yes为这个target开启按需加载资源。

  8. No为这个target关闭按需加载资源。

(二)创建和编辑tag

tag用来区分和管理按需加载资源。给一个资源添加一个或多个tag就能将其标记为按需加载资源。在运行时,所有管理按需加载资源的调用都是和tag相关,而不是单个资源。在运行时管理按需加载资源在管理按需加载资源中有讲到。

Xcode中的资源 tag

Xcode提供了管理tag和相关资源的工具。包括创建和编辑tag,添加和删除tag下的资源,指定操作系统在什么时刻下载tag关联的资源。

Resource Tags选项卡

Resource Tags选项卡在project editor中,用来浏览和编辑工程中全部的tag和相关资源。选项卡包括:

  • 添加按钮:用来创建新的tag。

  • 搜索框:用来查找指定的tag或资源。

  • tag编辑器:用来更改tag的名称,删除tag,增删tag下的资源。tag下全部资源所占的存储大小会显示在tag名称右边的圆括号中。大小是依据最后一次构建所选择的运行设备来计算的。

  • tag视图选择器:用来在查看全部tag和查看预获取分类tag之间切换。tag可以在app安装时下载,在安装之后预获取,或者在app运行时按需加载。预取优先级编辑器也会显示每个分类中资源所占的存储大小。大小是依据最后一次构建所选择的运行设备来计算的。

按需加载资源tag框

在按需加载资源tag框中,你可以快速浏览一个文件夹或资源,并为其添加删除tag。在Asset Catalog中,如果文件夹或者某个类型的资源可以加tag的话,这个框显示在Attributes inspector中,如下图所示。

创建tag

创建tag的第一步是检查你的app在运行时如何使用资源。看看你的app是否有以下几种资源:

  • 在任何时刻都必须是app的一部分。

  • 可以提升用户体验,但在启动app时不是必需的。包括高分辨率素材、高质量声音等等。

  • 在特定场景下才需要。

上面说的后两类的就有可能是按需加载资源。在app第一次启动后马上就要用到的资源可以设置为在安装后自动预获取。操作方法见预获取tag。每个tag下的资源总计大小不能超过2GB。按需加载资源的总计大小不能超过20GB。按需加载资源的大小是不算在app bundle的大小中的。更多信息,参见附录B:按需加载资源的大小限制。

一个tag的理想大小是不超过64MB。这能很好地平衡下载速度和本地存储大小,当设备的存储空间不足时可以进行清理。

tag的名称最好能区分出资源是如何使用的。例如,所有和森林场景有关的资源就可以起名叫forest-scenery。

创建好tag后就可以分配给资源了。一个资源可以添加多个tag。例如在下图中,游戏的资源是按关卡和地点来分割的。

如何创建一个新的tag

  1. 在project navigator中, 选择工程文件。

  2. 为需要新tag的target打开project editor 。

  3. 选择 Resource Tags 选项卡。

  4. 点击选项卡左上角的添加按钮(+)。

如下图所示,会显示一个新的tag输入框。

5. 输入tag的名称来替换占位符。

为资源添加tag

可以为任何有效的按需加载资源类型添加tag。具体的有效类型,参见附录A:

在Asset Catalog中添加tag

  1. 在project navigator中, 选择Asset Catalog。

  2. 在列表中选择一项 。

  3. 为选择的项目打开Attributes inspector。

  4. 在按需加载资源tag框,输入tag的名称。

    Xcode会根据输入的字符进行自动补全提示。

5. 按下Return键来确认输入的tag名称。

注意:输入一个新的名称,并按下Return键,会创建一个新的tag。

在按需加载资源tag框为工程中的某个文件添加tag

  1. 在project navigator中, 选择一个文件。

  2. 打开实用工具区,点击File inspector 按钮。

  3. 在按需加载资源tag框,输入tag的名称。

Xcode会根据输入的字符进行自动补全提示。

4. 按下Return键来确认输入的tag名称。

注意:输入一个新的名称,并按下Return键,会创建一个新的tag。

使用Resource Tags选项卡来给工程中的文件添加tag

  1. 在project navigator中, 选择工程文件。

  2. 为target打开project editor 。

  3. 选择 Resource Tags 选项卡。

  4. 在搜索框中,输入tag的名称。列表会根据搜索的文字进行过滤。

  5. 点击添加按钮(+),会弹出一个对话框。

6. 在输入框中,输入资源文件的名称。

7. 选中想要的资源文件,点击Add。这个资源文件就加上tag了。

注意: Asset Catalogs中的资源必须使用按需加载资源tag框来添加tag。

从tag中删除资源

可以通过在按需加载资源tag框删除tag,来将资源从tag中删除。也可以在Resource Tags 选项卡中删除资源。

使用Resource Tags选项卡来删除tag下的资源

  1. 在project navigator中, 选择工程文件。

  2. 为target打开project editor 。

  3. 选择 Resource Tags 选项卡。

  4. 在搜索框中,输入tag的名称。列表会根据搜索的文字进行过滤。

  5. 在tag对应的行中,点击左侧的小箭头来展开tag编辑器(如果没有展开的话)。

  6. 在tag编辑器中,选择列表中的资源文件。

  7. 在tag编辑器中,点击删除按钮(-)。

在Asset Catalog中添加tag

  1. 在project navigator中, 选择Asset Catalog。

  2. 在列表中选择一项 。

  3. 为选择的项目打开Attributes inspector。

  4. 在按需加载资源tag框,选择一个tag,按下Delete键。

在按需加载资源tag框为工程中的某个文件删除tag

  1. 在project navigator中, 选择一个文件。

  2. 打开实用工具区,点击File inspector 按钮。

  3. 在按需加载资源tag框,选择一个tag,按下Delete键。

预获取的tag

通常来说,操作系统是不会下载一个tag下的资源,直到app请求一个tag并且该tag的资源没有在设备上缓存。一些tag中会包含启动时需要或者启动后马上要用到的资源。

在Resource Tags选项卡的Prefetched界面下,可以把tag分配给三个预获取优先级分类的其中一个。界面展示了按预获取分类分组的tag。tag可以在分类间拖动。

  • 初始安装tag(Initial install tags)。只有在初始安装tag下载到设备后,app才能启动。这些资源会在下载app时一起下载。这部分资源的大小会包括在App Store中app的安装包大小。如果这些资源从来没有被NSBundleResourceRequest对象获取过,就有可能被清理掉。

  • 按顺序预获取tag(Prefetch tag order)。在app安装后会开始下载tag。tag会按照此处指定的顺序来下载。

  • 按需下载(Dowloaded only on demand)。当app请求一个tag,且tag没有缓存时,才会下载该tag。

将tag设置为随app安装

  1. 在project navigator中, 选择工程文件。

  2. 为target打开project editor 。

  3. 选择 Resource Tags 选项卡。

  4. 在tag视图选择器,点击Prefetched。

  5. 在内容区,点击Initial Install Tags分类旁边的小箭头。

  6. 在内容区,找到你想要随app安装的tag。

  7. 点击并拖动该tag到Initial Install Tags列表。

将tag设置为预获取

  1. 在project navigator中, 选择工程文件。

  2. 为target打开project editor 。

  3. 选择 Resource Tags 选项卡。

  4. 在tag视图选择器,点击Prefetched。

  5. 在内容区,点击Prefetched Tag Order分类旁边的小箭头。

  6. 在内容区,找到你想要预获取的tag。

  7. 点击并拖动该tag到Prefetched Tag Order列表。 tag在列表的位置会决定下载的顺序。列表最上面的tag会最先下载。

将tag设置为只在app请求时下载

  1. 在project navigator中, 选择工程文件。

  2. 为target打开project editor 。

  3. 选择 Resource Tags 选项卡。

  4. 在tag视图选择器,点击Prefetched。

  5. 在内容区,点击Downloaded Only On Demand分类旁边的小箭头。

  6. 在内容区,找到你想要按需下载的tag。

  7. 点击并拖动该tag到Downloaded Only On Demand列表。

(三)管理按需加载资源

下载和管理按需加载资源是由操作系统完成的。app使用NSBundleResourceRequest来:

  • 请求获取按需加载资源。

  • 通知操作系统某些资源不再使用。

  • 更新下载的优先级。

  • 追踪下载的进度。

  • 检查存储空间不足的通知。

当已下载的某些资源不再使用时,可以用NSBundle中的方法来设置保存优先级。

按需加载资源使用下面的4个方法来管理。

  1. app分配并初始化一个NSBundleResourceRequest对象。需要管理的tag必须在初始化时指定,不能更改。

  2. app请求获取一个tag下的资源。如果这些资源需要下载,可以更新下载的优先级,追踪下载进度。如果发生错误了,可以采取适当的措施。错误包括无效的tag、没有网络连接、无权使用蜂窝移动数据、没有足够的空间等等。

  3. app使用这些资源。这些资源的使用方式和该类型的其他资源一样。

  4. app结束获取这些资源,并通知系统不再使用这些资源。

在tag下载到设备后的任何时间都可以设置tag的保存优先级。

注意:每个NSBundleResourceRequest对象都只能用于一个请求访问/结束访问循环。

请求访问

app必须在使用tag的资源之前先请求访问这些tag。请求访问的第一步是为tag创建一个NSBundleResourceRequest对象。一个tag可以由多个NSBundleResourceRequest对象来管理。

每个NSBundleResourceRequest实例管理同一个bundle下的加了tag的资源。使用下面的两个方法来在初始化时设置被管理的tag和bundle:

  • 如果资源都在app的main bundle中,使用 initWithTags:。

  • 如果资源都在同一个自定义bundle中,使用 initWithTags:bundle: 。

注意:bundle可以设置为main bundle。

列表4-1展示了一个初始化资源管理器的一个例子,所有加tag的资源都在main bundle中。

列表4-1 初始化一个NSBundleResourceRequest实例

1
2
3
4
// Initialize an NSBundleResourceRequest with the desired tags
NSSet *tags = [NSSet setWithArray: @[@"birds", @"bridge", @"city"]];
// All the resources are in the main bundle so use the shorter initialization method
resourceRequest = [[NSBundleResourceRequest alloc] initWithTags:tags];

注意:tag和bundle只能在初始化时设置。

请求访问资源

在初始化NSBundleResourceRequest实例之后,就是请求访问了。当请求的所有tag下的所有资源都在本地存储中时,操作系统会持有这些资源,并使用回调通知app这些资源已经可以使用了。更多信息参见第三步按需加载资源的生命周期。

有两个方法来请求访问。当资源已在设备上时,这两个方法都可以允许访问。不同的是当资源不在设备上时会做什么。

  • beginAccessingResourcesWithCompletionHandler: 会从 App Store下载这些资源。

  • conditionallyBeginAccessingResourcesWithCompletionHandler: 不会下载资源。

两个方法都会在回调block中返回结果。所有的资源都必须已经在设备上才能使用。列表4-2展示了方法beginAccessingResourcesWithCompletionHandler:。

列表4-2 使用beginAccessingResourcesWithCompletionHandler:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// Request access to the tags for this resource request
[resourceRequest beginAccessingResourcesWithCompletionHandler:
                                 ^(NSError * __nullable error)
    {
        // Check if there is an error
        if (error) {
            // There is a problem, update app state (should inform user if appropriate)
            self.resourcesLoaded = NO;
            return;
        }
  
        // the resources associated with the the tags are loaded, start using them
        self.resourcesAvailable = YES;
    }
];

注意:在允许访问之后,不要使用同一个NSBundleResourceRequest实例再次请求访问。

检查tag是否已在设备上

有时当tag不在设备上时,你并不想开始下载它们。例如,当设备使用低带宽网络,并且高质量的图片和声音不在设备上时,你可以使用低质量资源。

当tag已在设备上,conditionallyBeginAccessingResourcesWithCompletionHandler:会允许访问。如果tag不在设备上,app需要调用beginAccessingResourcesWithCompletionHandler:来下载它们。列表4-3展示了一个检查tag是否在设备上的例子。

注意:如果conditionallyBeginAccessingResourcesWithCompletionHandler:返回YES,就不要调用beginAccessingResourcesWithCompletionHandler:了。

列表4-3 使用conditionallyBeginAccessingResourcesWithCompletionHandler:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// Request access to tags that may already be on the device
[resourceRequest conditionallyBeginAccessingResourcesWithCompletionHandler:
                                                 ^(BOOL resourcesAvailable)
    {
        // Check if the resources are available
        if (resourcesAvailable) {
            // the resources associated with the the tags are loaded, start using them
            self.highQualityResourcesAvailable = YES;
        else {
            // The resources are not on the device and need to be loaded
            // Queue up a call to custom method for loading the tags using
            // beginAccessingResourcesWithCompletionHandler:
            dispatch_async(dispatch_get_main_queue(), ^{
                [self loadLowerQualityTags];
            }
        }
    }
];

何时请求tag

因为从App Store下载tag会花一些时间,你可以在需要使用tag之前请求tag。下载时间取决于总共要下载的大小,网络连接的速度,以及操作系统能分配多少资源来处理下载。

在没有带宽限制的理想情况,在300Mbps的 802.11n或者LTE网络(299.6Mbps)上,下载一个64MB的tag至少要用1.7秒。但实际情况是连接到因特网的速度要远低于300Mbps。

下载优先级

资源请求有一个默认的优先级,这可以随时更改,包括下载时。低优先级使用更少的操作系统资源,为其他任务腾出资源。这也会降低下载速度。低优先级有利于最大化app执行效率。列表4-4展示了一个更改请求优先级的例子。

列表4-4 更改下载优先级

1
2
// The priority is a between 0.0 and 1.0
self.resourceRequest.loadingPriority = 0.1;

提高下载优先级会使用更多的操作系统资源,相应地提高下载速度,降低app效率。如果下载很紧急,app可以将下载优先级设置为NSBundleResourceRequestLoadingPriorityUrgent。这会告诉操作系统尽可能多地分配资源来处理下载。一个使用场景就是用户在下载完成之前什么也做不了。列表4-5展示了一个当用户需要等待时,设置紧急优先级的例子

列表4-5 提高请求的优先级

1
2
3
4
5
6
7
8
// Raise the priority based on the urgency
if (self.userWaiting) {
    // The user is waiting, request the maximum download time
    self.resourceRequest.loadingPriority = NSBundleResourceRequestLoadingPriorityUrgent;
else {
    // Set a higher priority
    self.resourceRequest.loadingPriority = 0.8;
}

上面的代码直接使用了一个固定浮点数设置优先级。你也可以根据app的效率来更新下载优先级。

追踪下载进度

在下载开始之后,请求会开始更新progress,这是一个NSProgress类型的属性。app通过对progress.fractionCompleted进行KVO来追踪下载进度。这需要开始和结束观察,以及添加当值改变时执行的代码。列表4-6展示了如何开始和结束观察进度。列表4-7展示了当值改变时执行的代码。

列表4-6 开始和结束追踪下载进度

1
2
3
4
5
// Start observing fractionCompleted for the progress
[self.resourceRequest.progress addObserver:self forKeyPath:@"fractionCompleted" options:NSKeyValueObservingOptionNew context:NULL];
  
// Stop observing fractionCompleted for the progress
[self.resourceRequest.progress removeObserver:self forKeyPath:@"fractionCompleted"];

列表4-7 当fractionCompleted的值改变时执行的代码

1
2
3
4
5
6
7
8
9
//
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    // Check for the progress object and key
    if ((object == self.resourceRequest.progress) && ([keyPath isEqualToString:@"fractionCompleted])) {
        double progressSoFar = self.resourceRequest.progress.fractionCompleted;
        // do something with the value
    }
}

追踪下载的两个重要用途是:

  • 调整下载优先级。如果下载时间过长可以提高优先级,如果时间充裕可以降低优先级。

  • 为用户提供下载进度反馈。可以使用一个简单的进度条来反馈fractionCompleted的值。

暂停和取消下载

正在进行的下载可以被暂停、恢复、取消。着通过progress属性,以及NSProgress提供的方法来完成。更多信息参见NSProgress类参考。

列表4-8 暂停、恢复、取消当前的下载

1
2
3
4
5
6
7
8
// Pause the current download
[self.resourceRequest.progress pause];
  
// Resume the current download
[self.resourceRequest.progress resume];
  
// Cancel the current download
[self.resourceRequest.progress cancel];

结束访问

当app不再使用资源时,结束访问能让操作系统可以回收存储空间。这也就是按需加载资源基础中按需加载资源的生命周期的第4步。有2种方法结束访问:

  • 给请求发送endAccessingResources,如列表4-9所示。

  • 释放这个请求。

列表4-9 结束对tag的访问

1
2
// End access by calling this method or deallocating the NSBUndleResourceRequest instance
[self.resourceRequest endAccessingResources];

在endAccessingResources调用之后,这个请求就不能再用于请求访问了。如果app还需要访问同一个tag,需要再重新创建一个NSBundleResourceRequest实例。

设置保留优先级

某些tag中的资源可能比其他的更重要。例如,应用内购买或者基本功能的资源就会被更频繁地用到。app可以为这些tag设置一个高保留优先级。当操作系统开始清理tag时,会从最低保留优先级开始。

可以使用NSBundle的方法来设置和检查保留优先级。

列表4-10 为tag检查和设置保留优先级

1
2
3
4
5
6
7
// Check the preservation priority for the llama in-app purchase module
double currentPriority = [[NSBundle mainBundle] preservationPriorityForTag:@"iap-llamas"];
  
// Set the priority to the maximum of 1.0 (the default is 0.0)
// The call to set the priority takes a set of tags
NSSet *tags = [NSSet setWithArray: @[@"iap-llamas"]];
[[NSBundle mainBundle] setPreservationPriority:1.0 forTags:tags];

低存储空间警告

当操作系统没有办法为当前正在请求的资源释放出足够的空间时,系统会发出一个通知。你的app应该停止访问所有不再使用的tag,如上面结束访问描述的。如果操作系统不能释放出足够空间,app会被终止。

例如,在一个有多个关卡的游戏中,用户正在第4关,app请求第3、5、6关的tag。当低存储空间警告发生时,app可以释放第3、6关的tag。列表4-11展示了注册低存储空间通知的代码。列表4-12展示了释放不需要tag的方法。

列表4-11 注册NSBundleResourceRequestLowDiskSpaceNotification通知

1
2
// End access by calling this method or deallocating the NSBUndleResourceRequest instance
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(lowDiskSpace:) name:NSBundleResourceRequestLowDiskSpaceNotification object:nil];

注册通知一般由app delegate或者主view来完成。

列表4-12 低存储空间通知的处理

1
2
3
4
5
6
7
8
9
10
11
12
// Notification handler for low disk space warning
-(void)lowDiskSpace:(NSNotification*)theNotification
{
    // Free the lower priority resource requests
    for (NSBundleResourceRequest *atRequest in self.lowPriorityRequests) {
        // End accessing the resources
        [atRequest endAccessingResources];
    }
  
    // clear lowPriorityRequests preventing multiple calls to endAccesingResource
    [self.lowPriorityRequests removeAllObjects];
}

lowPriorityRequests 不是由操作系统提供的。它是一个需要由app创建和维持的mutable set 。

(四)调试

在你开发的过程中可能会遇到几类问题。不同类别的问题需要使用不同的工具来调试。主要有以下几类问题:

  • 网络连接:慢速或无网络连接产生的问题。

  • 本地存储空间:本地存储空间不足无法下载。

  • 意外状态:tag处于意外状态。例如,一个tag显示正在使用中,但app的所有模块都已经结束访问了。

意外状态

调试意外状态最有用的工具就是Xcode中的磁盘仪表了。磁盘仪表中会显示tag的当前状态,如下图所示。

磁盘仪表会显示每个tag的大小和状态。大小是针对当前设备裁切后的。

tag的状态

表5-1描述了磁盘仪表中tag可能处于的状态。

表5-1 tag的状态

使用磁盘仪表 

在模拟器或真机上运行app都可以使用磁盘仪表。

打开磁盘仪表。

  1. 选择View > Navigators > Show Debug Navigator。

  2. 使用Scheme弹框选择一个target和设备。

  3. 选择Product > Run来启动app。app会在选择的设备上启动,并连接调试器。

  4. 在Debug Navigator中的列表中点击磁盘仪表。磁盘仪表会在workspace窗口的内容区显示。

  5. 向下滚到直到显示资源分类。你可以调整内容的大小来显示全部tag。

附录A:资源类型

下表列出了可以加tag的资源类型。

表A-1 资源类型

数据文件可以包括除了可执行的Swift、Objective-C、C、或者C++二进制包以外的任何类型数据。由脚本语言生成的文件可以用作资源。

附录B:资源大小限制

内存大小

在App Store 提交时和app运行时,资源的使用的内存大小是有限制的。

表B-1 资源大小

  • Slicing。表示这个大小是在App裁切之前还是之后。

  • app二进制包。表示裁切后的下载到设备上的安装包大小。

  • Initial install tags。裁切后标为初始安装tag的全部大小。

  • Initial install and prefetched tags。裁切后标为初始安装和预获取tag的全部大小。

  • In use on-demand resources。裁切后app在任何时刻使用中的tag的大小。只要有一个NSBundleResourceRequest 对象访问tag,tag就算是在使用中。

  • Hosted on-demand resources。由App Store托管的未裁切的大小。

iOS开发系列--NextPrevious On-Demand Resource Basics相关推荐

  1. iOS开发系列--Swift语言

    概述 Swift是苹果2014年推出的全新的编程语言,它继承了C语言.ObjC的特性,且克服了C语言的兼容性问题.Swift发展过程中不仅保留了ObjC很多语法特性,它也借鉴了多种现代化语言的特点,在 ...

  2. iOS开发系列--让你的应用“动”起来

    概览 在iOS中随处都可以看到绚丽的动画效果,实现这些动画的过程并不复杂,今天将带大家一窥iOS动画全貌.在这里你可以看到iOS中如何使用图层精简非交互式绘图,如何通过核心动画创建基础动画.关键帧动画 ...

  3. iOS开发系列--通知与消息机制

    http://www.cocoachina.com/ios/20150318/11364.html 概述 在多数移动应用中任何时候都只能有一个应用程序处于活跃状态,如果其他应用此刻发生了一些用户感兴趣 ...

  4. iOS开发系列--UITableView全面解析

    iOS开发系列--UITableView全面解析 2014-08-23 23:20 by KenshinCui, 2202 阅读, 18 评论, 收藏,  编辑 --UIKit之UITableView ...

  5. IOS开发系列--IOS程序开发概览

    IOS开发系列--IOS程序开发概览 2014-08-04 19:42 by KenshinCui, 9983 阅读, 51 评论, 收藏, 编辑 概览 终于到了真正接触IOS应用程序的时刻了,之前我 ...

  6. iOS开发系列--网络开发(转)

    iOS开发系列--网络开发 2014-10-22 08:34 by KenshinCui, 66365 阅读, 56 评论, 收藏, 编辑 概览 大部分应用程序都或多或少会牵扯到网络开发,例如说新浪微 ...

  7. iOS开发系列文章(持续更新……)

    iOS开发系列的文章,内容循序渐进,包含C语言.ObjC.iOS开发以及日后要写的游戏开发和Swift编程几部分内容.文章会持续更新,希望大家多多关注,如果文章对你有帮助请点赞支持,多谢! 为了方便大 ...

  8. iOS开发系列--数据存取

    原文地址为: iOS开发系列--数据存取 概览 在iOS开发中数据存储的方式可以归纳为两类:一类是存储为文件,另一类是存储到数据库.例如前面IOS开发系列-Objective-C之Foundation ...

  9. iOS开发系列--通讯录、蓝牙、内购、GameCenter、iCloud、Passbook详解

    代码改变世界 Posts - 69, Articles - 0, Comments - 812 Cnblogs Dashboard Login Home Contact Gallery RSS Ken ...

  10. IOS开发系列—Objective-C之内存管理

    概述 我们知道在程序运行过程中要创建大量的对象,和其他高级语言类似,在ObjC中对象时存储在堆中的,系统并不会自动释放堆中的内存(注意基本类型是由系统自己管理的,放在栈上).如果一个对象创建并使用后没 ...

最新文章

  1. Nature Method :Rob Knight发布Striped UniFrac算法轻松分析微生物组大数据
  2. PHP+MySQL手工注入问题及修复
  3. thinkphp5 获取当前的域名
  4. oracle 小计 排序,使用SQL实现小计,合计以及排序
  5. 面试题05. 替换空格
  6. 让微信扫描直接下载你的APK
  7. javamail 超时_为什么JavaMail连接超时太长
  8. 盘绕过苹果id方法_如何更换苹果ID?
  9. led透明屏生产厂家_LED透明屏厂家哪家好?2020年中国深圳LED透明屏品牌排行榜...
  10. 面向 Android* Jelly Bean 的英特尔® 凌动™ x86 映像安装说明 — 推荐
  11. 人工智能和金融是天作之合的5个理由
  12. MATLAB实现Otsu算法
  13. 【算法工程师】华为技术面面试记录
  14. 关于学习scala中lazy关键字的记录
  15. React-Native之轮播组件汇总 以及looped-carousel的介绍与使用
  16. CSDN博客编写快捷键
  17. 服务器状态错误是怎么回事,内部服务器错误500是什么?该如何解决?
  18. 永洪科技何春涛:中国企业数据技术的6大需求和解决之道
  19. android手机电视投影,教程向 | 手机投屏激光电视操作指南
  20. Spring AOP组合使用多个切入点表达式

热门文章

  1. python关键词采集_Python多线程采集百度相关搜索关键词
  2. python炫酷gui界面_如何炫酷的使用Python
  3. 对于半圆形的点击区域该怎么做_我做了一个傻瓜式热力图生成工具
  4. 系统学习机器学习之cox模型
  5. ADS2015导入飞思卡尔元器件模型 安装DesignKit
  6. 计算机毕设(附源码)JAVA-SSM基于远程协作的汽车故障诊断系统
  7. Ubuntu安装使用(一)
  8. Dev-C++ 一直提示源文件未编译,原因及解决办法
  9. ICIP论文结构整理
  10. 时间限制的命令(timeout)