Swift 包管理器 (SPM) 入门指南:现代 Swift 开发的基石
在现代软件开发中,高效地管理项目依赖是至关重要的。无论是引入第三方库以利用现有功能,还是将自己的代码组织成可复用的模块,一个强大的包管理器都能极大地提升开发效率和项目可维护性。对于 Swift 生态系统来说,Swift Package Manager (SPM) 正扮演着这样的核心角色。
SPM 是苹果官方推出的,深度集成于 Swift 工具链的依赖管理工具。它不仅让 Swift 项目能够方便地引入外部依赖,也为 Swift 代码库的构建、测试和分发提供了标准化的流程。如果你正在进行 Swift 开发,无论是构建 iOS/macOS 应用、服务器端应用还是命令行工具,掌握 SPM 都是一项必备技能。
本文将为你提供一份全面的 SPM 入门指南,从基本概念到实际操作,带你一步步走进 Swift 包管理器的世界。
1. 为什么选择 Swift Package Manager?
在 SPM 出现之前,Swift 开发者主要依赖 Carthage 和 CocoaPods 这两个第三方依赖管理器。它们各自有优点和缺点:
- CocoaPods: 功能强大,社区活跃,依赖解决能力强,支持动态库和静态库,但需要额外的 Ruby 环境安装,且对项目文件(
.xcodeproj
)的修改较多,可能引入冲突。 - Carthage: 更轻量,只负责构建和提供二进制文件,对项目文件修改少,但配置相对复杂,且不负责依赖的传递性管理(需要手动添加所有直接和间接依赖)。
SPM 作为官方解决方案,旨在结合两者的优点并提供更原生的体验:
- 原生集成: SPM 直接集成在 Swift 编译器和 Xcode 中,无需额外安装第三方工具(除了 Swift/Xcode 本身)。
- 简单易用: 无论是添加依赖还是创建自己的包,流程都相对直观。
- 跨平台支持: SPM 是 Swift 工具链的一部分,可以在 macOS、Linux 等支持 Swift 的平台上使用,对于服务器端 Swift (如 Vapor, Kitura) 或跨平台命令行工具开发尤其重要。
- 自动化管理: SPM 负责依赖的下载、构建、链接,以及依赖关系的解析和冲突解决。
- 高性能: 原生集成通常意味着更好的构建性能,且 SPM 有自己的缓存机制。
- 标准化: 提供了一套标准的项目结构和描述格式 (
Package.swift
),使得 Swift 代码的组织和分享更加统一。 - 确定性: 使用
Package.resolved
文件锁定依赖的具体版本,确保团队成员或在不同时间构建时使用相同的依赖版本,避免“在我机器上可以”的问题。
总而言之,SPM 是苹果和 Swift 社区推荐的现代 Swift 项目依赖管理方式,学习和使用它是迈向更高效、更标准的 Swift 开发的关键一步。
2. 前置条件
开始使用 SPM,你需要:
- 安装 Swift 工具链: 通常通过安装最新版本的 Xcode 来获得,Xcode 包含了 Swift 编译器和 SPM。
- 终端 (Terminal): 虽然 Xcode GUI 可以完成大部分操作,但了解并使用命令行工具 (
swift package
) 对于自动化、脚本编写或在非 GUI 环境下工作非常有用。
SPM 对项目结构有一定要求,但 Xcode 创建的新项目通常都满足这些要求。
3. 如何将 Swift 包添加到你的项目(消费者视角)
最常见的 SPM 使用场景是作为库的消费者,将现有的 Swift 包集成到你的应用或框架中。SPM 支持将包添加到应用项目 (.xcodeproj
或 .xcworkspace
) 或另一个 Swift 包中。
3.1 在 Xcode 中添加包 (推荐方式)
Xcode 提供了非常便捷的 GUI 界面来管理 SPM 依赖。
- 打开你的项目: 在 Xcode 中打开你的
.xcodeproj
或.xcworkspace
文件。 -
添加包:
- 选择菜单栏
File
->Add Packages...
。 - 或者,在项目导航器 (Project Navigator) 中,选择你的项目文件(顶部的蓝色图标),然后在项目设置 (Project Settings) 视图中,选择
Package Dependencies
标签页,点击底部的+
按钮。
- 选择菜单栏
-
输入包仓库 URL: 在弹出的搜索框中,输入你想要添加的 Swift 包的 Git 仓库 URL。这个 URL 通常是 HTTPS 格式,例如
https://github.com/Alamofire/Alamofire.git
。输入后,Xcode 会自动查找该仓库。 -
选择依赖规则 (Dependency Rule): 找到包后,你需要指定你想要使用的版本。SPM 提供了几种灵活的规则:
- Version (Up to Next Major): 使用指定版本(如
5.0.0
)或其之后的所有版本,直到下一个主版本更新之前(即会接受5.x.y
但不会接受6.0.0
)。这是最常用的推荐选项,因为它允许你自动获取 bug 修复和新特性(在 minor 或 patch 版本中),同时避免引入可能包含重大变更的主版本。 - Version (Up to Next Minor): 使用指定版本(如
5.8.0
)或其之后的所有版本,直到下一个次要版本更新之前(即会接受5.8.x
但不会接受5.9.0
)。比上一个更保守。 - Version (Exact): 只使用指定的精确版本(如
5.8.1
)。最保守,确保版本完全一致,但不会自动获取任何更新。 - Branch: 使用特定分支的最新提交。通常用于开发或测试阶段,不推荐用于生产环境,因为分支 HEAD 随时可能变化,导致构建不确定。
- Commit: 使用特定提交的哈希值。提供最高的确定性,但如果你需要更新包,必须手动修改提交哈希。通常用于锁定到一个已知的稳定状态。
根据你的需求选择合适的规则。对于初学者和大多数应用开发,”Up to Next Major Version” 是一个很好的起点。
- Version (Up to Next Major): 使用指定版本(如
-
添加包到目标 (Add to Target): 在窗口的底部,Xcode 会显示包中的产品 (Products) 和你项目中的目标 (Targets)。一个包可以包含一个或多个库 (Libraries) 或可执行文件 (Executables) 作为其产品。你需要选择将包的哪些产品链接到你项目中的哪个目标。例如,如果你添加的是 Alamofire,它可能只有一个名为
Alamofire
的库产品。你需要勾选你想要使用 Alamofire 的那个应用或框架目标。 -
完成添加: 点击
Add Package
按钮。
Xcode 此时会开始下载依赖并解析依赖关系。这个过程可能需要一些时间,取决于你的网络速度和依赖的数量。下载的包会存储在你的主目录下的一个共享缓存中 (~/Library/Caches/org.swift.swiftPM/
),以便不同项目可以复用。
成功添加后,你会看到:
- 在项目导航器的
Package Dependencies
部分出现了你添加的包。 - 在项目的
Package Dependencies
标签页中列出了所有已添加的包及其版本规则。 - Xcode 会自动生成或更新一个
Package.resolved
文件(通常位于.xcodeproj
或.xcworkspace
同级目录下),该文件精确记录了每个依赖(包括传递性依赖)被解析到的具体版本。务必将Package.resolved
文件添加到你的版本控制中 (如 Git),以确保团队成员和构建系统都能构建出相同的版本。
3.2 在代码中使用导入的包
一旦包被成功添加到你的目标,你就可以在 Swift 代码中像使用任何模块一样使用它了。只需在你需要使用该包的代码文件的顶部添加 import PackageName
语句即可,例如 import Alamofire
。然后你就可以调用该库提供的类型和函数了。
3.3 使用命令行管理依赖 (进阶)
虽然 Xcode GUI 方便,但了解命令行对于自动化或调试很有帮助。在你的项目根目录(包含 .xcodeproj
或 Package.swift
文件)中,可以使用 swift package
命令:
- 编辑依赖: 要手动修改
Package.swift
文件来添加或修改依赖,然后运行swift package resolve
来解析和下载依赖,并更新Package.resolved
。 - 更新依赖: 运行
swift package update
。这会尝试根据Package.swift
中定义的规则,更新依赖到最新的兼容版本,并更新Package.resolved
。 - 清理构建文件: 运行
swift package clean
可以清理之前构建生成的中间文件。
如果你是为一个纯 SPM 包(没有 .xcodeproj
)添加依赖,你将直接编辑该包的 Package.swift
文件,并在 dependencies
数组中添加新的依赖。
swift
// 示例 Package.swift 文件片段
let package = Package(
name: "MyProject",
dependencies: [
// 添加 Alamofire 依赖
.package(url: "https://github.com/Alamofire/Alamofire.git", from: "5.8.1"),
// 添加另一个依赖
.package(url: "https://github.com/SnapKit/SnapKit.git", .upToNextMajor(from: "5.0.0"))
],
targets: [
// ... targets 定义
]
)
添加或修改 Package.swift
后,在终端中运行 swift package resolve
或在 Xcode 中构建项目,SPM 就会处理新的依赖。
4. 如何创建你自己的 Swift 包(生产者视角)
除了使用别人的包,你也可以创建自己的 Swift 包来组织代码,供自己其他项目使用或分享给社区。
4.1 使用命令行创建包 (推荐方式)
命令行是创建标准 Swift 包最快捷的方式。
- 打开终端: 导航到你想要创建包的父目录。
- 创建包: 使用
swift package init
命令:- 创建库 (Library):
swift package init --type library
- 这是最常见的类型,用于创建可被其他项目导入和使用的代码模块。
- 创建可执行文件 (Executable):
swift package init --type executable
- 用于创建可以独立运行的命令行工具。
- 创建空包 (Empty):
swift package init --type empty
- 创建一个只有
Package.swift
文件的空包,适用于手动配置复杂结构。
- 创建一个只有
- 创建库 (Library):
例如,要创建一个名为 MyAwesomeLibrary
的库:
bash
cd /path/to/your/development/folder
swift package init --type library --name MyAwesomeLibrary
SPM 会为你生成以下标准目录结构:
MyAwesomeLibrary/
├── Sources/
│ └── MyAwesomeLibrary/
│ └── MyAwesomeLibrary.swift # 默认生成的源文件
├── Tests/
│ └── MyAwesomeLibraryTests/
│ └── MyAwesomeLibraryTests.swift # 默认生成的测试文件
├── .gitignore
└── Package.swift # 包的清单文件
4.2 使用 Xcode 创建包
你也可以通过 Xcode GUI 创建 Swift 包:
- 选择菜单栏
File
->New
->Package...
。 - 填写包名称,选择存储位置。
- 选择包类型 (Library 或 Executable)。
- 勾选是否包含单元测试。
- 点击
Create
。
Xcode 也会生成类似的目录结构,并在 Xcode 中打开该包。
4.3 理解生成的结构
Package.swift
: 这是包的清单文件,使用 Swift 语言编写。它定义了包的名称、平台支持、产品、依赖以及最重要的——目标 (Targets)。你需要在这里声明你的代码是如何组织的。Sources/
: 这个目录包含了你的包的实际源代码。按照 SPM 的约定,Sources
下的每个子目录通常对应一个目标 (Target)。例如,Sources/MyAwesomeLibrary/
包含了MyAwesomeLibrary
目标的代码。Tests/
: 这个目录包含了你的包的单元测试代码。同样,Tests
下的每个子目录通常对应一个测试目标,并对应于一个源代码目标。例如,Tests/MyAwesomeLibraryTests/
包含了测试MyAwesomeLibrary
目标的代码。SPM 使用 XCTest 框架进行测试。.gitignore
: 一个标准的 Git 忽略文件,忽略 SPM 生成的构建文件和缓存。
5. Package.swift
文件详解
Package.swift
是 Swift 包的灵魂,它是一个 Swift 文件,定义了包的所有元数据和结构。它使用 PackageDescription
模块提供的 API 来描述包的各个方面。
以下是一个典型的 Package.swift
文件结构:
“`swift
// swift-tools-version: 5.9 // 指定 Swift 工具链版本
import PackageDescription
let package = Package(
// 1. 包名称
name: “MyAwesomeLibrary”,
// 2. 支持的平台 (可选)
// 如果是用于应用开发,建议指定最低平台版本
platforms: [
.macOS(.v10_15),
.iOS(.v13),
.tvOS(.v13),
.watchOS(.v6),
.visionOS(.v1),
],
// 3. 产品 (Products) - 定义包对外暴露的内容
products: [
// 定义一个库产品
.library(
name: "MyAwesomeLibrary", // 产品名称
targets: ["MyAwesomeLibrary"] // 包含哪些目标 (Targets)
// libraryKind: .static or .dynamic (可选,默认通常由构建系统决定)
),
// 如果是可执行包,可以定义一个可执行产品
// .executable(
// name: "mycommandlineapp",
// targets: ["mycommandlineapp"]
// )
],
// 4. 依赖 (Dependencies) - 定义包依赖的外部 SPM 包
dependencies: [
// 依赖一个远程 Git 仓库的包
.package(url: "https://github.com/Alamofire/Alamofire.git", from: "5.8.1"),
// 依赖另一个远程 Git 仓库的包,使用不同的版本规则
.package(url: "https://github.com/SnapKit/SnapKit.git", .upToNextMajor(from: "5.0.0")),
// 依赖本地路径的包 (用于开发调试)
// .package(path: "../AnotherLocalPackage")
],
// 5. 目标 (Targets) - 定义包内部的代码模块
targets: [
// 源代码目标 (Library Target)
.target(
name: "MyAwesomeLibrary", // 目标名称
dependencies: [
// 该目标依赖包内部的其他目标 或 外部依赖包的产品
.product(name: "Alamofire", package: "Alamofire"), // 依赖 Alamofire 包的 Alamofire 产品
// .target(name: "AnotherInternalTarget"), // 依赖包内的另一个目标
],
path: "Sources/MyAwesomeLibrary", // 源代码路径 (相对于 Package.swift)
resources: [ // 包含资源文件 (如图片、json等)
.process("Resources") // 处理 Resources 目录下的所有资源
// .copy("SomeSpecificFile.txt") // 复制指定文件
],
// swiftSettings: [...], // Swift 编译器设置
// linkerSettings: [...], // 链接器设置
// plugins: [...] // 构建插件
),
// 测试目标 (Test Target)
.testTarget(
name: "MyAwesomeLibraryTests", // 测试目标名称
dependencies: [
// 测试目标通常依赖它要测试的源代码目标
.target(name: "MyAwesomeLibrary"),
// 测试框架依赖 (如 Swift-Snapshot-Testing)
// .product(name: "SnapshotTesting", package: "swift-snapshot-testing"),
],
path: "Tests/MyAwesomeLibraryTests" // 测试代码路径
// resources: [...] // 测试资源
)
// 如果有多个源代码模块,可以定义更多 target
// .target(
// name: "AnotherInternalTarget",
// dependencies: [...]
// path: "Sources/AnotherInternalTarget"
// )
]
)
“`
让我们详细 breakdown 每个部分:
swift-tools-version:
: 必须在文件顶部以注释的形式指定,告诉 SPM 使用哪个版本的工具链来解析这个Package.swift
文件。随着 SPM 的发展,Package.swift
的语法和支持的功能也会更新,指定版本可以确保向后兼容性。import PackageDescription
: 导入 SPM 定义包结构的模块。let package = Package(...)
: 创建一个Package
实例,包含了包的所有配置。name
: 包的名称,必需。platforms
: (可选)指定该包支持的最低平台版本。这对于面向特定平台(如 iOS, macOS)的库非常重要,确保使用者不会在旧版本系统上引入不兼容的代码。如果你的包是纯 Swift 逻辑,不依赖特定平台 API,可以省略此项。products
: 定义包构建完成后可以对外提供的可执行单元。主要有两种类型:.library
: 一个库,可以被其他包或应用依赖。你可以指定name
和它包含的targets
。库可以是静态的 (.static
) 或动态的 (.dynamic
),不指定时 SPM 或 Xcode 会根据使用场景和依赖关系自动决定。.executable
: 一个可执行文件,可以独立运行。通常只有一个目标。
一个包可以定义多个产品。
dependencies
: 定义该包所依赖的外部 SPM 包。使用.package
语法,指定包的 Git 仓库 URL 和版本规则。.package(url: String, from: Version)
: 指定 URL 和一个最低版本号。SPM 会使用该版本或更高兼容版本(取决于工具链版本和依赖规则)。.package(url: String, .upToNextMajor(from: Version))
: 指定 URL 和一个最低版本号,接受该版本及之后的所有次要/补丁版本,直到下一个主版本。.package(url: String, .upToNextMinor(from: Version))
: 指定 URL 和一个最低版本号,接受该版本及之后的所有补丁版本,直到下一个次要版本。.package(url: String, .exact(Version))
: 只接受指定的精确版本。.package(url: String, .branch(String))
: 依赖特定分支的最新提交。.package(url: String, .revision(String))
: 依赖特定提交哈希。.package(path: String)
: 依赖本地文件系统路径上的另一个包,用于本地开发和测试。
targets
: 包的核心,定义了实际的代码模块和它们的构建方式。一个包可以有多个目标。主要类型:.target
: 一个源代码模块,可以是库的一部分或可执行文件的主要部分。它有name
,可以指定dependencies
(依赖包内部的其他目标或外部依赖包的产品),path
(相对于Package.swift
的源代码目录),以及可选的resources
、swiftSettings
等。.testTarget
: 一个用于编写单元测试和集成测试的特殊目标。它通常依赖于要测试的源代码目标,并使用 XCTest 框架。
目标之间的依赖使用.target(name:)
或.product(name: package:)
指定。.product
用于引用外部依赖包暴露的产品。
6. 在 Xcode 中开发 Swift 包
将 Swift 包添加到 Xcode 项目后,你可以在 Xcode 中直接打开和编辑该包的代码。在项目导航器的 Package Dependencies
部分,展开你添加的包,你可以看到它的源文件和测试文件。双击文件即可在 Xcode 中编辑。
如果你是创建自己的包,你可以直接在 Xcode 中打开该包目录下的 Package.swift
文件,Xcode 会将整个包作为一个项目来管理,你可以在其中编写代码、运行测试。
7. 构建、测试和运行
- 构建:
- Xcode: 构建包含 SPM 依赖的项目或直接构建 SPM 包时,Xcode 会自动处理依赖的下载、构建和链接。只需像往常一样选择目标并点击构建按钮 (
Cmd + B
)。 - 命令行: 在包的根目录下(包含
Package.swift
),运行swift build
命令来构建包。如果包是可执行类型,构建成功后,可执行文件通常位于.build/debug/
或.build/release/
目录下。
- Xcode: 构建包含 SPM 依赖的项目或直接构建 SPM 包时,Xcode 会自动处理依赖的下载、构建和链接。只需像往常一样选择目标并点击构建按钮 (
- 测试:
- Xcode: 打开 Test Navigator (
Cmd + 6
),你可以看到包中的测试目标和具体的测试用例。点击运行按钮即可执行测试。 - 命令行: 在包的根目录下,运行
swift test
命令来运行包中的所有测试。
- Xcode: 打开 Test Navigator (
- 运行 (仅限可执行包):
- Xcode: 选择可执行目标并运行 (
Cmd + R
)。 - 命令行: 在包的根目录下,运行
swift run [target-name]
命令来构建并运行指定的可执行目标。如果包只有一个可执行目标,[target-name]
可以省略。
- Xcode: 选择可执行目标并运行 (
8. 资源文件处理 (Resources)
SPM 支持在包中包含资源文件(如图片、JSON、本地化字符串等)。在目标的定义中,使用 resources
参数指定资源:
swift
.target(
name: "MyAwesomeLibrary",
dependencies: [],
path: "Sources/MyAwesomeLibrary",
resources: [
// 将 Resources 目录下的所有文件复制到目标 bundle 中
.process("Resources"),
// 或者只复制特定文件
// .copy("Data/config.json")
]
)
.process
: 这是推荐的方式。SPM 会根据平台对资源进行优化处理(例如,为 iOS 上的图片生成不同分辨率)。处理后的资源会放在一个由 SPM 管理的 bundle 中。.copy
: 直接将文件或目录复制到目标 bundle 中,不做任何处理。适用于不需要优化的文件类型。
在代码中访问这些资源需要找到 SPM 生成的 bundle。通常,你可以通过 Bundle.module
访问当前包的资源 bundle:
swift
// 在 MyAwesomeLibrary.swift 中访问资源
let bundle = Bundle.module
if let url = bundle.url(forResource: "config", withExtension: "json") {
// 读取资源文件
let data = try Data(contentsOf: url)
// ...
}
注意: Bundle.module
是一个 SPM 提供的便利属性,仅在将你的包作为依赖添加到应用项目时可用。如果你直接构建和运行你的包(例如一个命令行工具),或者在测试目标中访问资源,访问 bundle 的方式可能有所不同,需要根据具体情况调整。对于测试,通常可以直接访问测试源文件旁边的资源文件路径。
9. 版本锁定 (Package.resolved
)
Package.resolved
文件记录了每个直接和间接依赖在最后一次解析/更新时被锁定的精确版本、分支或提交哈希。这是实现构建确定性的关键。
- 重要性: 确保你的项目在任何时间、任何机器上都能使用完全相同的依赖版本进行构建。这避免了由于依赖版本变动导致的不可预测的行为或构建失败。
- 版本控制: 务必将
Package.resolved
文件提交到你的版本控制系统中 (Git)。当你克隆一个项目时,SPM 会读取Package.resolved
文件来获取精确的依赖版本,而不是仅仅依赖Package.swift
中的版本规则。 - 更新: 当你运行
swift package update
或通过 Xcode GUI 更新包时,SPM 会重新解析依赖并更新Package.resolved
文件。
10. 本地依赖和开发流程
在开发或调试一个包时,你可能需要让另一个项目或包依赖你本地正在修改的版本,而不是远程仓库的版本。这时可以使用本地依赖:
swift
dependencies: [
// 依赖本地路径的包
.package(path: "../MyAwesomeLibrary"),
// 其他远程依赖...
]
在 Package.swift
中使用 path:
参数指定本地包的相对或绝对路径。这样,SPM 会直接使用该路径下的代码,而不是从远程仓库下载。当你修改本地包的代码时,依赖它的项目会立即看到这些改动,无需提交或推送。
当你准备发布或共享你的包时,你需要将本地依赖改回远程仓库的 URL 和版本规则。
另一种本地开发方式是使用 swift package edit <PackageName>
命令。这个命令会将指定的远程依赖包克隆到你当前包的 Dependencies
目录下,并修改 .Package.resolved
文件指向本地路径。你可以直接在 Dependencies
目录下修改该依赖的代码。当你完成修改后,可以使用 swift package unedit <PackageName>
恢复到从远程仓库拉取。这个方法也很方便用于调试或向依赖库贡献代码。
11. 常见问题与故障排除
- 依赖解析失败: 检查
Package.swift
文件中的依赖 URL 是否正确,版本规则是否与仓库中存在的标签/分支匹配。可能是网络问题导致无法访问仓库。检查依赖包是否有传递性依赖冲突。 - 构建失败: 可能是代码错误,或者依赖未正确链接到目标。在 Xcode 中检查目标的 “Frameworks, Libraries, and Embedded Content” 设置,确保 SPM 管理的产品已被正确列出。清理构建缓存 (
swift package clean
或 Xcode 的 Clean Build Folder)。 - Xcode 无法识别模块: 确保你在代码中使用了正确的
import PackageName
。检查包产品是否已正确添加到你的目标中。重启 Xcode 有时也能解决这类问题。 Package.resolved
冲突: 在团队协作中,如果多人同时修改依赖,可能导致Package.resolved
文件冲突。解决冲突时,需要仔细查看哪些依赖被更改,并合并期望的版本。通常以更新的版本为准,但要小心潜在的不兼容性。
12. 局限性
虽然 SPM 发展迅速并日趋成熟,但仍然存在一些需要注意的地方:
- 生态系统: 虽然 SPM 社区日益壮大,但一些老旧的库可能仍然只支持 CocoaPods 或 Carthage。不过越来越多的新库和活跃维护的库都已支持 SPM。
- 二进制依赖: SPM 对预编译的二进制框架 (
.framework
或.xcframework
) 的支持相对较新(需要 Swift 5.3+ 和 Xcode 12+ 支持 XCFrameworks)。虽然现在已经可用,但在某些复杂场景下可能不如基于源码的依赖灵活。 - 资源处理: 尽管有了
resources
参数,但在某些复杂的跨平台或混合语言项目中,资源管理仍可能需要额外配置。
13. 总结
Swift Package Manager 已经成为 Swift 开发中管理依赖和组织代码的标准方式。它深度集成于 Swift 工具链和 Xcode,提供了简单、高效、跨平台的包管理体验。
通过本文,你应该了解了:
- SPM 的优势以及为什么应该使用它。
- 如何在 Xcode 和命令行中将 Swift 包添加到你的项目。
- 如何创建你自己的 Swift 包。
Package.swift
文件各个部分的含义和配置方法。- 如何在 Xcode 中开发和管理 Swift 包。
- 构建、测试和运行包的基本命令。
- 资源文件的处理方式。
Package.resolved
文件的作用和重要性。- 本地依赖和开发流程。
- 一些常见的故障排除技巧。
现在,你已经具备了使用 Swift Package Manager 的基础知识。开始在你的项目中使用 SPM 吧,尝试添加一些常用的开源库,或者将你自己的通用代码打包成可复用的 Swift 包。随着实践的深入,你会越来越熟练地掌握这个强大的工具,让你的 Swift 开发工作更加高效和愉快!
如果你想深入了解更多高级特性,可以查阅官方的 Swift Package Manager 文档,它是最权威和详细的参考资料。