首页 > NSBundle如何在bundle中搜索指定的资源?

NSBundle如何在bundle中搜索指定的资源?

最近看苹果文档《Bundle Programming Guide》,发现其中就NSBundle定位资源的搜索模式前后描述不一致。

P31, "localized resources in bundles"中提到

When looking for resources in your bundle, the bundle-loading code looks first in any region-specific directories, followed by the language-specific directory. And if neither localized directory contains the resource, the bundle-loading code looks for an appropriate nonlocalized resource.
在bundle中搜索资源时,相关代码会首先搜索特定地区目录,然后搜索特定语言目录。如果上述两个地方都没有找到相应的资源,那么会在寻找非本地话资源。

个人对以上的搜索顺序理解为:region.lproj目录--->language.lproj目录--->根目录

但是,还是这份文档P38 "The Bundle Search Pattern"中又提到:

Then the bundle searches for the resource in the following order:

  1. Global (nonlocalized) resources

  2. Region-specific localized resources (based on the user’s >region preferences)

  3. Language-specific localized resources (based on the user’s language preferences)

  4. Development language resources (as specified by the CFBundleDevelopmentRegion in the bundle’s Info.plist file.)
    在bundle中寻找特定资源的顺序如下:1.非本地化资源中 2.地区目录 3.语言目录 4.开发语言目录

按照这段话,搜索的顺序变成了:根目录--->region.lproj目录--->language.lproj目录

自相矛盾的不止这一处。P16 "Anatomy of an iOS Application Bundle"中又提到:

Even if you provide localized versions, however, you should always include a default version of these files at the top-level of your application bundle. The default version is used in situations where a specific localization is not available.
即使对某些资源进行了本地化,依然要在根目录下放一个默认版本的文件,以防没有针对某些语言或地区进行本地化。

可以,在P38 "The Bundle Search Pattern"中,给出了完全相反的叙述:

Because global resources take precedence over language-specific resources, there should never be both a global and localized version of a given resource. If a global version of a resource exists, language-specific versions of the same resource are never returned.
由于非本地化资源(这里的global就是non-localized,文档中有说明)的优先级高于本地化资源,同一个资源绝对不要同时出现一个本地化版本和一个非本地化版本。如果这样的话,本地化的版本永远不会被获取。

请问是我傻逼了还是苹果傻逼了。这文档就没人看吗?2015年6月更新的文档。


大体没错,算指代不清,第一段描述确实是错了。。。Bundle 的搜索顺序是:

  1. 先在根目录找(global resources/nonlocalized resources)

  2. 根目录找不到就去用户对应地区文件(中文中国,中文台湾)夹找

  3. 然后语言文件夹(中文)

  4. 都没有就 fallback 到 Localization native development region (以下简称 DR)指定的文件夹找(默认是 en,项目设置里改)

都找不到就瞎。

放资源的原则

  1. 根目录放所有语言共用的东西,不管什么地区语言,都用同一个。

  2. 然后 DR 文件夹里放所有需要本地化的东西,任何没有做本地化处理的语言、地区都会 fallback 到这里。

  3. 各种语言的文件夹要有和 DR 中一样的一套资源。当然内容是各个语言本地化之后的。

可以看到按照这个原则来排布本地化资源,按前面的搜索顺序去搜索的话是不会出现冲突的。

你提到的:

依然要在根目录下放一个默认版本的文件

可以理解为根目录下面默认版本的 DR 本地化文件夹(没改的话就是 en.lproj),而不是一个默认版本的资源文件。所有没有本地化的语言的资源文件都会回到这个“默认版本”来。

英文描述中也有暗示:a default version of these files 这“些”文件的一个默认版本,不是一个文件的默认版本。

这里估计是你最大的困惑了,你可能认为这里的文件层级是这样的:

Root
|
+-abc.png
|
+-zh_CN.lproj
  |
  +-abc.png

按前面的搜索顺序,显然不对,你永远只能获取 Root 下的 abc.png。(事实上也是这样。。。)然而我认为文档中的默认版本指代的是语言文件夹,而不是特定的本地化资源。也就是说结构是这样:

Root
|
+-en.lproj   // 指定的 DR 文件夹,你放在根目录下的“默认版本”
|  |
|  +-abc.png
|
+-zh_CN.lproj
  |
  +-abc.png

you should place most nonlocalized resources in this top-level directory

非本地化资源放在最顶层,本地化资源放在哪?当然是各个本地化文件夹下面,不然就不叫本地化资源了。

感觉大体上矛盾就在这,剩下的题主自己也能理清楚了。


When looking for resources in your bundle, the bundle-loading code looks first in any region-specific directories, followed by the language-specific directory. And if neither localized directory contains the resource, the bundle-loading code looks for an appropriate nonlocalized resource.

在bundle中搜索资源时,相关代码会首先搜索特定地区目录,然后搜索特定语言目录。如果上述两个地方都没有找到相应的资源,那么会在寻找非本地话资源。

不洗地了,个人认为这段描述确实有错。正确顺序如前文描述。

Then the bundle searches for the resource in the following order:
Global (nonlocalized) resources
Region-specific localized resources (based on the user’s >region preferences)
Language-specific localized resources (based on the user’s language preferences)
Development language resources (as specified by the CFBundleDevelopmentRegion in the bundle’s Info.plist file.)
在bundle中寻找特定资源的顺序如下:1.非本地化资源中 2.地区目录 3.语言目录 4.开发语言目录

就是前文所述的搜索顺序,开发语言目录就是在项目配置中指定的 fallback 。所有没有本地化的语言就会使用这个语言的资源。

Even if you provide localized versions, however, you should always include a default version of these files at the top-level of your application bundle. The default version is used in situations where a specific localization is not available.
即使对某些资源进行了本地化,依然要在根目录下放一个默认版本的文件,以防没有针对某些语言或地区进行本地化。

恩恩,默认版本的本地化文件夹。

Because global resources take precedence over language-specific resources, there should never be both a global and localized version of a given resource. If a global version of a resource exists, language-specific versions of the same resource are never returned.
由于非本地化资源(这里的global就是non-localized,文档中有说明)的优先级高于本地化资源,同一个资源绝对不要同时出现一个本地化版本和一个非本地化版本。如果这样的话,本地化的版本永远不会被获取。

没错。放了的话就成图示1那样了:

Root
|
+-abc.png  // 非本地化
|
+-zh_CN.lproj
  |
  +-abc.png  // 本地化(永远不会被获取到)

【热门文章】
【热门文章】