Swift Package Manager: 从零开始构建与集成
Swift Package Manager (SPM) 是 Apple 官方推出并推荐的依赖管理工具,用于自动化 Swift 代码的分发。它与 Swift 构建系统深度集成,提供了一种统一的方式来管理项目中的第三方库,并简化了在不同平台(iOS, macOS, tvOS, watchOS, Linux, Windows)上共享代码的流程。
本文将从零开始,详细介绍如何创建一个 Swift Package,以及如何将其集成到您的 Xcode 项目中。
1. SPM 简介与优势
在 SPM 出现之前,iOS/macOS 开发者主要依赖 CocoaPods 和 Carthage 来管理第三方库。SPM 的出现解决了这些工具的一些痛点,并带来了以下优势:
- 原生支持: 作为 Swift 工具链的一部分,SPM 无缝集成于 Xcode 和 Swift 构建系统,无需额外安装其他工具。
- 跨平台: 支持所有 Swift 运行的平台,包括 Apple 平台、Linux 和 Windows。
- 易用性: 通过简单的 Swift 语法定义
Package.swift文件,即可声明依赖关系。 - 版本控制集成: 直接利用 Git 仓库进行版本管理,方便地指定依赖的版本。
- 模块化: 鼓励开发者将代码组织成独立的模块,提高代码复用性和可维护性。
2. 环境准备
要开始使用 SPM,您需要:
- Xcode: 推荐使用最新稳定版 Xcode,它内置了 Swift 和 SPM。
- macOS: 虽然 SPM 也支持 Linux 和 Windows,但在 macOS 上结合 Xcode 使用是主流。
3. Part 1: 构建您的第一个 Swift Package
我们将创建一个简单的 Swift Package,包含一个计算器功能。
3.1 初始化一个新的 Swift Package
首先,打开终端,导航到您希望创建项目的目录,然后执行以下命令:
bash
mkdir MyCalculatorPackage
cd MyCalculatorPackage
swift package init --type library
mkdir MyCalculatorPackage: 创建一个新的文件夹作为您的 Package 根目录。cd MyCalculatorPackage: 进入该目录。swift package init --type library: 初始化一个库类型的 Swift Package。如果您想创建一个可执行的命令行工具,可以使用--type executable。
执行后,您会看到如下的文件结构:
.
├── Sources/
│ └── MyCalculatorPackage/
│ └── MyCalculatorPackage.swift
├── Tests/
│ └── MyCalculatorPackageTests/
│ └── MyCalculatorPackageTests.swift
├── .gitignore
└── Package.swift
Sources: 存放您的源代码。每个子文件夹代表一个 Target。Tests: 存放您的单元测试代码。Package.swift: 包的清单文件,定义了包的名称、产品、目标和依赖。.gitignore: Git 忽略文件。
3.2 理解 Package.swift 文件
打开 Package.swift 文件,内容大致如下:
“`swift
// swift-tools-version: 5.9
// The swift-tools-version declares the minimum version of Swift tools required to build this package.
import PackageDescription
let package = Package(
name: “MyCalculatorPackage”,
products: [
// Products define the executables and libraries a package produces, making them visible to other packages.
.library(
name: “MyCalculatorPackage”,
targets: [“MyCalculatorPackage”]),
],
targets: [
// Targets are the basic building blocks of a package, defining a module or a test suite.
// Targets can depend on other targets in this package, and on products in packages this package depends on.
.target(
name: “MyCalculatorPackage”),
.testTarget(
name: “MyCalculatorPackageTests”,
dependencies: [“MyCalculatorPackage”]),
]
)
“`
swift-tools-version: 定义了构建此包所需的最低 Swift 工具版本。name: 包的名称。products: 定义了此包公开的产品。.library: 定义一个库产品,可以被其他项目或包引用。name是库的名称,targets是该库包含的目标。
targets: 定义了包中的模块。.target: 定义一个源代码目标。默认情况下,它的源文件在Sources/<target name>目录下。.testTarget: 定义一个测试目标。它通常依赖于它所测试的源代码目标。dependencies: 指定此目标依赖的其他目标或包产品。
3.3 编写 Package 代码
编辑 Sources/MyCalculatorPackage/MyCalculatorPackage.swift 文件,添加一个简单的计算器结构体:
“`swift
import Foundation
public struct Calculator {
public init() {}
public func add(_ a: Int, _ b: Int) -> Int {
return a + b
}
public func subtract(_ a: Int, _ b: Int) -> Int {
return a - b
}
public func multiply(_ a: Int, _ b: Int) -> Int {
return a * b
}
public func divide(_ a: Int, _ b: Int) -> Double? {
guard b != 0 else { return nil }
return Double(a) / Double(b)
}
}
“`
注意:为了使 Calculator 结构体和其方法能在外部使用,它们必须声明为 public。
3.4 编写测试代码
编辑 Tests/MyCalculatorPackageTests/MyCalculatorPackageTests.swift 文件,为计算器功能添加测试:
“`swift
import XCTest
@testable import MyCalculatorPackage // 使用 @testable 导入内部类型进行测试
final class MyCalculatorPackageTests: XCTestCase {
func testAdd() {
let calculator = Calculator()
XCTAssertEqual(calculator.add(1, 2), 3)
XCTAssertEqual(calculator.add(-1, 1), 0)
}
func testSubtract() {
let calculator = Calculator()
XCTAssertEqual(calculator.subtract(5, 3), 2)
XCTAssertEqual(calculator.subtract(3, 5), -2)
}
func testMultiply() {
let calculator = Calculator()
XCTAssertEqual(calculator.multiply(2, 3), 6)
XCTAssertEqual(calculator.multiply(-2, 3), -6)
}
func testDivide() {
let calculator = Calculator()
XCTAssertEqual(calculator.divide(6, 2), 3.0)
XCTAssertNil(calculator.divide(6, 0)) // 测试除以零的情况
}
}
“`
3.5 构建与测试 Package
在 MyCalculatorPackage 目录下,您可以通过终端命令来构建和运行测试:
bash
swift build // 构建包
swift test // 运行包中的所有测试
如果一切顺利,您将看到构建成功和测试通过的输出。
4. Part 2: 集成 Swift Package 到 Xcode 项目
现在我们已经有了一个可用的 Swift Package,接下来是如何将其集成到您的 iOS 或 macOS 项目中。
4.1 创建一个新的 Xcode 项目
如果您还没有,请创建一个新的 Xcode 项目 (例如:一个 iOS App)。
4.2 添加 Swift Package 依赖 (推荐方式:Xcode UI)
这是最常见和最简单的方法:
- 在 Xcode 中,选择您的项目导航器中的项目文件 (顶部的蓝色图标)。
- 在主窗口中,选择 “Project” 或 “Target” (通常是您的应用程序 Target),然后点击 “Package Dependencies” 选项卡。
- 点击底部的 “+” 按钮。
- 在弹出的对话框中,您有几种方式添加依赖:
- 远程仓库: 如果您的 Package 已经上传到 Git 仓库 (如 GitHub),可以直接粘贴仓库的 URL (e.g.,
https://github.com/your-username/MyCalculatorPackage.git)。 - 本地包: 对于仍在开发中的本地包,您可以点击 “Add Local…” 并选择您的
MyCalculatorPackage文件夹。Xcode 会自动识别Package.swift文件。
- 远程仓库: 如果您的 Package 已经上传到 Git 仓库 (如 GitHub),可以直接粘贴仓库的 URL (e.g.,
- 添加 URL 后,Xcode 会解析该仓库,并允许您选择依赖规则 (Version, Branch, Commit)。对于初次集成,您可以选择 “Up to Next Major Version” 并使用默认版本。
- 点击 “Add Package” 完成添加。
- Xcode 会将包添加到您的项目,并显示在 “Package Dependencies” 列表中。同时,在左侧的项目导航器中,您会看到 “Package Dependencies” 部分出现了您的
MyCalculatorPackage。
4.3 将 Package 产品链接到 Target
添加包依赖后,您还需要将包中提供的产品 (如 MyCalculatorPackage 库) 链接到您的应用程序 Target:
- 在项目导航器中,选择您的应用程序 Target。
- 选择 “General” 选项卡。
- 滚动到 “Frameworks, Libraries, and Embedded Content” 部分。
- 点击左下角的 “+” 按钮。
- 在列表中找到
MyCalculatorPackage(Library 类型),选择它,然后点击 “Add”。
现在,您的应用程序 Target 已经可以访问 MyCalculatorPackage 中定义的公开类型了。
4.4 在应用程序中使用 Package
在您的应用程序代码中 (例如 ViewController.swift),您可以导入并使用 Calculator 结构体:
“`swift
import UIKit
import MyCalculatorPackage // 导入您的 Swift Package 模块
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let calculator = Calculator()
let sum = calculator.add(10, 5)
print("Sum: \(sum)") // 输出:Sum: 15
if let divisionResult = calculator.divide(10, 2) {
print("Division: \(divisionResult)") // 输出:Division: 5.0
} else {
print("Cannot divide by zero!")
}
}
}
“`
运行您的应用程序,您将在控制台看到计算结果。
5. 高级主题 (简述)
- 本地 Package 的开发: 您可以将本地 Package 拖拽到 Xcode 项目的同一工作空间 (
.xcworkspace) 中进行并行开发。这样,对 Package 的修改会立即反映在应用程序中。 - 二进制 Target: SPM 支持引入预编译的二进制框架 (
.xcframework),这对于分发闭源库非常有用。 - 版本管理: 在
Package.swift文件中,可以使用upToNextMajor(from: "1.0.0"),upToNextMinor(from: "1.0.0"),.exact("1.0.0")等规则来指定依赖的版本范围。 - Package Collections: Apple 和社区提供 Package Collections,可以方便地发现和添加可信赖的 Swift Packages。
6. 总结
Swift Package Manager 提供了一个强大、原生且易于使用的工具,用于管理 Swift 项目中的依赖。通过本文的引导,您应该已经能够从零开始创建一个 Swift Package,并成功将其集成到您的 Xcode 项目中。SPM 极大地简化了 Swift 代码的模块化和分发,是现代 Swift 开发不可或缺的一部分。