文章目录
-
- [一、SPM 是什么?](#一、SPM 是什么?)
- 二、核心概念
-
- [2.1 Package(包)](#2.1 Package(包))
- [2.2 Products(产物)](#2.2 Products(产物))
- [2.3 Targets(目标)](#2.3 Targets(目标))
- [2.4 Dependencies(依赖)](#2.4 Dependencies(依赖))
- [三、Package.swift 清单文件详解](#三、Package.swift 清单文件详解)
- 四、常用命令速查
- [五、在 Xcode 中使用 SPM](#五、在 Xcode 中使用 SPM)
-
- [5.1 添加依赖](#5.1 添加依赖)
- [5.2 本地包引用](#5.2 本地包引用)
- [5.3 Package.resolved 文件](#5.3 Package.resolved 文件)
- [六、🔥 外网访问性问题及解决方案(重点)](#六、🔥 外网访问性问题及解决方案(重点))
- 七、最佳实践总结
-
- [7.1 版本管理](#7.1 版本管理)
- [7.2 项目结构](#7.2 项目结构)
- [7.3 团队协作建议](#7.3 团队协作建议)
- [7.4 性能优化](#7.4 性能优化)
- [八、SPM vs CocoaPods 迁移建议](#八、SPM vs CocoaPods 迁移建议)
- 九、总结
本文系统介绍 SPM 的核心概念、实战用法,并重点讲解国内开发者最常遇到的外网访问性问题及其解决方案。
一、SPM 是什么?
Swift Package Manager(简称 SPM / SwiftPM)是 Apple 官方为 Swift 语言打造的依赖管理工具 ,自 Swift 3.0 起内置于工具链中,Xcode 11 起深度集成于 IDE。它能够自动化完成依赖包的下载、编译、链接及管理全流程,支持 iOS、macOS、watchOS、tvOS、Linux 等多平台。
与 CocoaPods、Carthage 相比,SPM 的核心优势:
| 特性 | SPM | CocoaPods | Carthage |
|---|---|---|---|
| 官方原生支持 | ✅ | ❌ | ❌ |
| 零额外环境依赖 | ✅ | 需 Ruby | 需安装 |
| 源码级集成 | ✅ | ✅ | 二进制 |
| 跨平台 (Linux) | ✅ | ❌ | ❌ |
| 无中央索引 | 去中心化 | 有 Trunk | 无 |
二、核心概念
2.1 Package(包)
包含 Swift 源代码及 Package.swift 清单文件的目录集合,是 SPM 管理的基本单位。
2.2 Products(产物)
包对外提供的成果物:
- Library:可重用组件,供其他代码导入使用
- Executable:可执行程序
2.3 Targets(目标)
构建单元,包含一组源代码文件。一个 Package 可包含多个 Target,Target 之间可以相互依赖。
2.4 Dependencies(依赖)
SPM 使用 Git 标签 + URL 来获取依赖,没有中央包索引(不同于 npm/CocoaPods)。
三、Package.swift 清单文件详解
swift
// swift-tools-version: 5.9
// 声明构建该包所需的最低 Swift 工具链版本
import PackageDescription
let package = Package(
name: "MyAwesomeLib",
// 支持的平台及最低版本
platforms: [
.iOS(.v15),
.macOS(.v12)
],
// 对外暴露的产物
products: [
.library(
name: "MyAwesomeLib",
targets: ["MyAwesomeLib"]
),
.executable(
name: "my-tool",
targets: ["MyTool"]
)
],
// 依赖声明
dependencies: [
// 精确版本
.package(url: "https://github.com/Alamofire/Alamofire.git", exact: "5.8.1"),
// 范围版本(推荐)
.package(url: "https://github.com/apple/swift-log.git", from: "1.5.0"),
// 区间版本
.package(url: "https://github.com/apple/swift-nio.git", "2.50.0"..<"3.0.0"),
// 分支依赖(开发阶段)
.package(url: "https://github.com/some/repo.git", branch: "develop"),
// 本地依赖
.package(path: "../LocalLib")
],
// 目标定义
targets: [
.target(
name: "MyAwesomeLib",
dependencies: [
.product(name: "Logging", package: "swift-log")
],
path: "Sources"
),
.executableTarget(
name: "MyTool",
dependencies: ["MyAwesomeLib"]
),
.testTarget(
name: "MyAwesomeLibTests",
dependencies: ["MyAwesomeLib"]
)
]
)
四、常用命令速查
bash
# 初始化项目
swift package init --type library # 创建库
swift package init --type executable # 创建可执行程序
# 依赖管理
swift package resolve # 解析依赖
swift package update # 更新所有依赖到允许的最新版本
swift package show-dependencies # 查看依赖树
# 构建与测试
swift build # 构建
swift build -c release # Release 构建
swift test # 运行测试
# 包发布
swift package dump-package # 输出包的 JSON 描述
swift package archive-source # 归档源码(用于发布)
# 编辑依赖(本地调试)
swift package edit Alamofire --revision <commit>
swift package unedit Alamofire
五、在 Xcode 中使用 SPM
5.1 添加依赖
- 打开项目 → File → Add Package Dependencies...
- 输入包的 Git URL(如
https://github.com/Alamofire/Alamofire.git) - 选择版本规则(Up to Next Major / Exact Version 等)
- 点击 Add Package
5.2 本地包引用
直接将包含 Package.swift 的文件夹拖入 Xcode 项目导航器即可。
5.3 Package.resolved 文件
Xcode 会自动生成 Package.resolved 文件(位于 .xcodeproj/project.xcworkspace/xcshareddata/swiftpm/),记录所有依赖的精确版本和 commit hash,务必提交到版本控制以确保团队一致性。
六、🔥 外网访问性问题及解决方案(重点)
内容过不了审,科学上网/镜像
七、最佳实践总结
7.1 版本管理
swift
// ✅ 推荐:使用语义化版本范围
.package(url: "...", from: "1.2.0") // >= 1.2.0 且 < 2.0.0
.package(url: "...", "1.2.0"..<"1.5.0") // 精确范围
// ❌ 避免:使用分支依赖(不稳定)
.package(url: "...", branch: "main")
7.2 项目结构
MyPackage/
├── Package.swift
├── Package.resolved # 提交到 Git
├── Sources/
│ ├── MyLib/
│ │ ├── MyLib.swift
│ │ └── Extensions/
│ └── MyTool/
│ └── main.swift
├── Tests/
│ └── MyLibTests/
│ └── MyLibTests.swift
└── README.md
7.3 团队协作建议
- 始终提交
Package.resolved到版本控制 - 使用
from:而非exact:声明依赖,保持灵活性 - 定期执行
swift package update并跑通测试 - 对关键依赖使用
exact:锁定版本 - 在 CI 中配置好理代/镜像,避免构建失败
7.4 性能优化
bash
# 使用 --disable-automatic-resolution 避免自动解析
swift build --disable-automatic-resolution
# 并行构建(默认已开启)
swift build --parallel
# 指定构建目录(SSD 加速)
swift build --build-path /tmp/spm-build
八、SPM vs CocoaPods 迁移建议
| 场景 | 建议 |
|---|---|
| 新项目 | 直接使用 SPM |
| 纯 Swift 项目 | 优先迁移到 SPM |
| 含大量 ObjC 依赖 | 可保留 CocoaPods,逐步迁移 |
| 需要资源文件 (xib/assets) | SPM 5.3+ 已支持 resources |
| 需要二进制分发 | SPM 5.3+ 支持 Binary Targets |
九、总结
SPM 作为 Apple 官方推荐的依赖管理方案,已经成为 Swift 生态的事实标准。对于国内开发者而言,网络问题是使用 SPM 最大的痛点,但通过合理配置 Git 理代、使用镜像、或开启理代工具的增强模式,完全可以获得流畅的开发体验。
推荐优先级:
- 🥇 Git 按域名理代 + 理代工具 TUN 模式(最稳定)
- 🥈 SPM Mirror 配置(无需改代码)
- 🥉 国内镜像源替换(适合依赖少的项目)
- 本地引用(离线/CI 兜底方案)