【IOS】 Swift Package Manager (SPM) 指南

文章目录

    • [一、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 添加依赖

  1. 打开项目 → FileAdd Package Dependencies...
  2. 输入包的 Git URL(如 https://github.com/Alamofire/Alamofire.git
  3. 选择版本规则(Up to Next Major / Exact Version 等)
  4. 点击 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 团队协作建议

  1. 始终提交 Package.resolved 到版本控制
  2. 使用 from: 而非 exact: 声明依赖,保持灵活性
  3. 定期执行 swift package update 并跑通测试
  4. 对关键依赖使用 exact: 锁定版本
  5. 在 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 理代、使用镜像、或开启理代工具的增强模式,完全可以获得流畅的开发体验。

推荐优先级

  1. 🥇 Git 按域名理代 + 理代工具 TUN 模式(最稳定)
  2. 🥈 SPM Mirror 配置(无需改代码)
  3. 🥉 国内镜像源替换(适合依赖少的项目)
  4. 本地引用(离线/CI 兜底方案)

相关推荐
SKH.6 分钟前
网络(4)HTTP协议与TCP并发服务器
网络·tcp/ip·http
(Charon)9 分钟前
【C++】网络缓冲区设计(一):为什么需要Buffer?输入输出缓冲区与统一接口
网络
getapi20 分钟前
1 在 macOS 电脑上更新 Flutter iOS 应用到 App Store
flutter·macos·ios
可乐鸡翅yeah_24 分钟前
App WebView 加载 M3U8 流媒体踩坑,安卓 iOS 混合开发播放异常定位
android·ios·harmonyos·m3u8·m3u8在线播放
lzfshub29 分钟前
Open-DIS Python发送DIS实体状态PDU:实现坦克炮塔与主炮部件参数
java·网络·python·dis
SatanII1 小时前
OpenStack核心组件详解|Keystone+Glance+Nova+Cinder原理与实操笔记
网络·笔记·openstack
吹什么轩1 小时前
linux网络:UDP原理
linux·网络·udp
东坡肘子1 小时前
当 Mac mini 的价格不再 mini -- 肘子的 Swift 周报 #152
人工智能·swiftui·swift
啊阿狸不会拉杆10 小时前
《计算机网络-自顶向下方法》5.4 ISP之间的路由选择:BGP 读书笔记
网络·计算机网络·接口隔离原则
Delite80211 小时前
摆脱实验室束缚:便携式卡尔费休微量水分检测技术与现场应用解析
大数据·网络·人工智能