使用 Swift 包捆绑资源

5/8/2022 swiftiosspm

原文:https://developer.apple.com/documentation/swift_packages/bundling_resources_with_a_swift_package (opens new window)

将资源文件添加到您的 Swift 包并在您的代码中访问它们。

# 概览

如果你在软件包清单中用Swift版本为5.3或更高的工具声明,你可以将资源与你的源代码捆绑成Swift包。例如,Swift包可以包含资产目录、故事板,等等。

# 添加资源文件

与源代码类似,Xcode将资源的作用范围扩大到一个 target。将资源文件放到与它们所属的target相对应的文件夹中。例如,MyLibrary目标的任何资源都需要放置在Sources/MyLibrary中。 然而,可以考虑为资源使用一个子文件夹,以区分它们与源文件。例如,把所有的资源文件放到一个名为"Resources"的目录中,结果是所有的资源文件都放在Sources/MyLibrary/Resources。

要将资源添加到 Swift 包,请执行以下任一操作:

  • 将它们拖入Xcode中的项目导航器。
  • 从Xcode的文件菜单中,选择添加文件到[packageName]。
  • 使用Finder或终端应用程序。

当您在 Swift 包中添加资源时,Xcode 会检测 apple 平台的常见资源类型,并自动将其视为一种资源。例如,对于以下资源,您不需要对您的包清单进行修改。

  • Interface Builder 文件;例如,XIB文件和storyboards
  • Core Data 文件;例如,xcdatamodeld文件
  • Asset 目录
  • 用来提供本地化资源的.lproj文件夹

如果你添加了一个Xcode默认不作为资源的资源文件,你必须在你的包清单中配置它,如在下一节所述。

# 明确声明或排除资源

要添加一个Xcode不能自动处理的资源,请在你的包清单中明确声明它为一个资源。下面的例子假设 text.txt 驻留在 Sources/MyLibrary 中,并且你想把它包含在 MyLibrary 目标中。要明确地将其声明为包资源,您需要将其文件名传递给包清单中目标的初始化器。

targets: [
    .target(
        name: "MyLibrary",
        resources: [
            .process("text.txt")]
    ),
]

注意上面的示例代码是如何使用process(_:localization:)函数的。当你显式地声明一个资源时,你必须选择这些规则中的一个来告诉Xcode如何处理这个资源文件:

  • 处理规则 对于大多数使用情况,使用process(_:localization:)来应用这个规则,并让Xcode根据你构建包的平台来处理资源。例如,Xcode可以为一个支持这种优化的平台优化图像文件。如果您将处理规则应用于一个目录的路径,Xcode将该规则递归地应用于该目录的内容。如果对一个资源没有特殊处理,Xcode 会将该资源复制到资源包的顶级目录中。

  • 复制规则 一些 Swift 包可能要求资源文件保持不动,或者为资源保留一定的目录结构。使用 copy(_😃 函数来应用这一规则,并让 Xcode 将资源原样复制到资源包的顶层。如果您向复制规则传递一个目录路径,Xcode将保留该目录的结构。

如果一个文件驻留在目标文件夹内,而你不希望它成为包的资源,请把它传递给目标初始化器的排除参数。下一个例子假设 instructions.md 是一个包含文档的 Markdown 文件,位于 Sources/MyLibrary,不应该成为包的资源包的一部分。这段代码显示了如何通过将该文件添加到排除文件列表中,将其排除在目标文件之外。

targets: [
    .target(
        name: "MyLibrary",
        exclude:["instructions.md"]
    ),
]

一般来说,避免把不是资源的文件放在目标的源文件夹中。如果这不可行,避免单独排除每个文件,把你想排除的所有文件放在一个目录中,并把目录路径添加到排除文件的数组中。

# 在代码中访问资源

当你构建你的 Swift 包时,Xcode 将每个 target 视为一个 Swift 模块。如果一个 target 包括资源,Xcode 会为每个模块创建一个资源包和一个关于 Bundle 的内部静态扩展来访问它。使用该扩展来定位包的资源。例如,使用下面的方法来检索您与包捆绑的属性列表的URL:

let settingsURL = Bundle.module.url(forResource: "settings", withExtension: "plist")

Important

当你访问资源时,总是使用Bundle.module。一个包不应该对资源的确切位置做出假设。

如果你想让依赖你的 Swift 包的应用程序可以使用某个包的资源,请为它声明一个公共常量。例如,使用下面的方法向使用你的 Swift 包的应用程序公开一个 plist 文件:

let settingsURL = Bundle.module.url(forResource: "settings", withExtension: "plist")
上次更新: 5/8/2022, 9:56:05 PM