Ff44762d70ab5afc7c153523d1410bd0
在 Xcode 中使用 Swift Package

WWDC 2019 Session 408: Adopting Swift Packages in Xcode

目前,在 macOS/iOS 开发中,我们通常使用 CocoaPodsCarthage 等非官方工具来管理项目工程中对第三方开源库的依赖。

Swift Package Manager(Swift 包管理器,一般简称 SwiftPM 或者 SPM)是苹果官方提供的一个用于管理源代码分发的工具,旨在使分享代码和复用其他人的代码变得更加容易。该工具可以直接帮助我们编译和链接 Swift packages(包),管理依赖关系、版本控制,以及支持灵活的代码分发和团队协作。

关于 Swift Package Manager 的详细介绍,可以参考去年的 WWDC 2018 Session 411: Getting to Know Swift Package Manager,以及我总结的这篇文章:

SwiftPM 一开始仅支持 macOS 和 Linux 平台上的 Swift 开发,且只能通过命令行的方式来使用。在最新的 Xcode 11 中集成了 libSwiftPM,并提供了图形化操作界面,使 Swift Package 支持 iOS/watchOS/tvOS 等平台。

下文我们将介绍如何在 Xcode 11 中使用 Swift Package 引入第三方开源库或私有代码库。

1. 如何添加 Package

我们先通过 Xcode 11 新建一个 Swift iOS 工程,假设名为 MyTestProject,然后可以通过如下两种方式添加 Swift Package 依赖:

  • Xcode Menu -> File -> Swift Packages -> Add Package Dependency...

  • 在 Xcode 工程中选中当前 Project 名称 -> 选择 Swift Packages -> 点击 + 图标添加

在弹出的窗口中,我们可以输入要依赖的 Package 的 git 仓库地址,例如,我们这里要在工程中添加 Yams 这个 Swift YAML 文件解析的开源库,则可以在输入框中填写其在 GitHub 上的 git url,如下图所示:

此外,我们可以在 Xcode -> Preferences... -> Accounts 中添加并登录自己的 GitHub/GitLab 账号或者公司内部私有 Git 服务器账号,然后就可以在 Choose Package Repository 窗口中直接选择你自己的或者已关注的 Swift Package,如下图:

选择好要依赖的 Package 后,点击 Next 按钮进行版本号设置。我们可以指定 Package 的版本号范围,规则如下,与 CocoaPods 类似:

  • Up to Next Major: 当前指定的版本号到下一个大版本号之间的最新版本,例如 2.0.0 ~ 3.0.0(不包含 3.0.0)
  • Up to Next Minor: 当前指定的版本号到下一个次版本号之间的最新版本,例如 2.0.0 ~ 2.1.0(不包含 2.1.0)
  • Range: 指定的两个版本号之间的最新版本,例如 2.1.0 ~ 2.7.2(不包含 2.7.2)
  • Exact: 指定使用某一具体的版本号

同时,我们也可以指定要依赖当前 Package git 仓库的某一个分支或者某一次 commit。

最后,勾选当前 Package 要添加到工程中的哪些 Targets,即可。

添加好 Package 之后,我们就可以在 Xcode 工程中查看到相关信息,如下图:

接下来我们就可以在代码中 import Yams 然后调用它的相关 API 了。

2. Package 概览

下面我们介绍一下 Swift Package 的内部结构。

一个 Package(包)由 Swift 源码文件和一个清单文件组成。这个清单文件被命名为 Package.swift,它使用 PackageDescription 模块来定义包的名称、内容以及依赖关系。

Yams 为例,它包含的内容如下:

  • Package.swift: 包的清单文件,用于描述包的名称、内容、依赖关系、支持的 Swift 版本号;
  • Sources: 源码文件夹,通常包括 C/C++ 代码和 Swift 代码等;
  • Tests: 单元测试代码

Package.swift 文件的大致内容如下:

另外,如果一个 Package 依赖了另一个 Package,也需要在 Package.swift 文件中进行声明。例如,有一个 Package 叫 "DesignTheme",它依赖了 "DesignFont",则需要在 "DesignTheme" 的 Package.swift 文件中添加如下依赖代码:

dependencies: [
    .package(url: "http://github.com/WWDC19/DesignFont.git"),
]

此时,当在 Xcode 工程的 Swift Packages 中添加了 "DesignTheme",同时就会自动下载依赖 "DesignFont",不需要我们再手动添加了。

因此,对于一个 Xcode 工程,当其依赖了一些 Swift Packages 后,在编译链接时,SwiftPM 会自动编译每个 Package 并链接到主可执行文件中。

PS: 对于 SwiftPM 的一些基本概念,例如:Modules、Packages、Products、Dependencies、Targets 等,在 Swift.org 官网已经有非常详细的描述和定义,另外,也可以参见我之前写的这篇文章,这里不再赘述。

3. Package 依赖详解

本节我们详细介绍一下 Swift Package 之间互相依赖的一些细节。

如前面所述,假如我们在 Demo 工程(名为 "Lunch")中,除了引入 "Yams" Package 外,又引入了一个 "DesignTheme" Package,如下图:

top Created with Sketch.