【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 兜底方案)

相关推荐
白色冰激凌2 小时前
[SECS/GEM研究] (四)HSMS 用TCP取代串口
网络·c++·网络协议·secs/gem
黑化旺仔2 小时前
iOS - 计算器仿写
ios
三言老师2 小时前
CentOS7 / 8 yum 查询软件安装路径实操
运维·服务器·网络·centos
倚栏听雨_ylty2 小时前
H3C交换机关闭Telnet和HTTP服务实例
运维·网络·tcp/ip·网络安全
zhaocarbon2 小时前
WKWebView 拦截 POST/PUT方法 丢失body的问题解决
ios·xcode·webview
东坡肘子2 小时前
不是模型变慢了,是任务变大了 -- 肘子的 Swift 周报 #146
人工智能·swiftui·swift
xywww1682 小时前
Claude Opus 5 API 接入实战:国内项目上线前的网络、Key、限流和排错清单
大数据·linux·网络·数据库·云计算·aws
ShineWinsu2 小时前
对于Linux:http的解析
linux·网络·c++·网络协议·http·请求·响应
白猫不黑2 小时前
SQL注入实战:手工注入全流程详解
网络·数据库·sql·web安全·网络安全·信息安全