16

WWDC 2020 - Swift Package Manager

 3 years ago
source link: https://kemchenj.github.io/2020-06-29/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

虽然 Swift Package Manager 发布到现在已经四年了,但采用率一直很低,无法完全替代 Cocoapods,不过今年情况将会有所改善,SwiftPM 今年迎来两个非常重要的功能:

  1. 二进制依赖分发
  2. 资源文件

二进制依赖

在去年 Xcode 11 集成了 SwiftPM 的功能,让我们可以以源码形式分发 Library,并且也引入了 XCFramework 来分发闭源 Library。

今年 Xcode 12 将会把它们结合到一起,提供二进制依赖库的支持,在下面的章节里我们将会介绍如何集成,分发和制作二进制依赖。

集成

包含了二进制文件的 Swift Package 在集成时不需要任何特殊的设置,它们也是一个普通的 Package.product ,像之前一样在 target 的 dependencies 里通过名字指定即可:

let package = Package(
    name: "package",
    products: [
        .executable(name: "package", targets: ["package"])
    ],
    dependencies: [
        .package("https://github.com/JohnnyAppleased2020/BinaryEmoji", from: "1.0.0")
    ],
    targets: [
        .target(name: "package", dependencies: ["Emoji"])
    ]
)

分发

需要注意,二进制依赖在 Swift 5.3 及以上才能使用:

// swift-tools-version: 5.3

Swift 5.3 里新增了一种新的 Target 类型 binaryTarget 来指定打包好的二进制文件:

let package = Package(
    name: "Emoji",
    products: [
        .library(name: "Emoji", targets: ["Emoji"]),
    ],
    targets: [
        .binaryTarget(
            name: "Emoji",
            url: "https://example.com/emoji/Emoji-1.0.0.xcframework.zip",
            checksum: "6d9888a1a27418674b4d7c31732f6d60e60734ceb11a0ce9b54d1871918d9c194"
        )
    ]
)

在分发二进制依赖时需要注意几点:

  • 目前只支持苹果平台,为了实现的便捷复用了已有的 XCFramework 格式,它支持动态和静态链接,并且可以同时支持多个平台。
  • 支持本地路径或者 https 链接。
  • 在使用本地路径时指向的可以是 XCFramework 的路径或者是 XCFramework 压缩后的 zip 文件,而 https 链接则只能指向 zip 文件。

制作

目前 XCFramework 的制作必须依托于 xcodebuild ,所以需要先使用 swift package generate-xcodeproj 生成 Xcode 项目文件,然后:

  1. 在 Build Settings 里将 Build Libraries for Distribution 选项改为 YES
  2. 使用 xcodebuild archive 打包 framework 文件。
  3. 使用 xcodebuild -create-xcframework 将各个平台的 framework 文件合并为 xcframework。

更具体的细节可以查看 Binary Frameworks in Swift - WWDC2019

资源文件

今年的 Xcode 12 我们可以给 Swift Package 添加图片,storyboard 以及其它资源文件,同时也可以本地化这些资源文件。并且资源文件的添加使用的是现有的 API,所以也兼容之前版本的操作系统。

添加资源文件

SwiftPM 会根据文件的拓展名来进行处理,有一部分文件的使用目的非常明确,Xcode 会自动帮我们处理,只要添加到目录里即可:

eEj6nuA.png!mobile

但有一部分文件它们的使用目的并不明确,例如 shell 脚本,文件夹,它们可能并不需要打包到 Package 里,此时我们就需要手动声明这些文件的处理规则:

BzyyIb.png!mobile

接下来让我们通过一个例子来了解具体的操作,重新回顾一下 Swift Package 的目录结构,我们会在 Sources 文件夹里看到与 target 同名的目录,目录里会存放着这个 target 的所有代码文件:

IrQBNfE.png!mobile

更具体的规则大家可以查看 Adopting Swift Packages in Xcode - WWDC19

接着我们来看 GameLogic 目录的结构,下面我们可以看到 storyboard 和 xcassets 不需要做任何的额外声明,直接添加到对应的目录里即可。

但 Internal Notes.txt 有些特别,它只是开发过程中使用的文档,我们不希望它也被打包到 Package 里,此时我们可以通过 excludes 参数进行指定:

VBju6rz.png!mobile

如果我们要添加一些运行时需要的资源文件,就可以通过 resources 参数进行指定,大部分资源文件都可以使用 process 指定,此时它们会根据对应的平台和打包方式自动进行处理:

Y7RrIn6.png!mobile

有时我们需要目录在打包到 Package 之后也能保持它的结构,那么此时就可以使用 copy 选项:

YBZzYnj.png!mobile

UjiMvmz.png!mobile

.process 选项会使用 SwiftPM 预设的规则自动进行处理:

.copy

.copy 没有规则,只是单纯的复制:

  • 可以用来覆盖预设的规则。
  • 目录的复制会递归进行(深复制)。

3eMN7vi.png!mobile

访问资源文件

资源文件的访问会沿用现有的 Foundation.Bundle ,这意味着 macOS 和 Linux 都可以共享同一套代码。

SwiftPM 会给所有带资源文件的 Target 自动合成当前 Bundle 的声明:

Bundle.module
SWIFTPM_MODULE_BUNDLE

访问资源文件:

// Swift
let image = UIImage(named: "Logo", in: Bundle.module)

// Objective-C
UIImage *image = [UIImage imageNamed:@"Logo" inBundle:SWIFTPM_MODULE_BUNDLE];

需要注意:warning:, Bundle.module 会被声明为 internal:

extension Bundle {
    internal var module: Bundle { get }
}

如果要让外部也能访问 Package 内的资源文件,推荐框架作者提供类型安全的外部接口。

本地化

Package 内的资源文件也支持本地化,我们需要在 Package.swift 声明默认的语言 defaultLocalization

let package = Package(
    name: "DiceUI",
    defaultLocalization: "en",
    ...
)

存放资源的目录名称需要使用对应的 Language ID + Locale ID + .lproj ,例如 en.lproj

Language and Locale ID - developer.apple.com

本地化的资源通常是:

.strings
.stringDicts

uq6FRjV.png!mobile


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK