跳到主要内容

CocoaPods 只读后怎么办?iOS 工程从 CocoaPods 迁移到 SPM

CocoaPods trunk 将在 2026 年 12 月 2 日变为只读,已发布的版本仍能 pod install,但依赖不再更新。本文讲清影响和是否该迁移,给出常用库的 SPM 支持对照和迁移到 Swift Package Manager 的 7 个步骤。

CocoaPods 只读从 2026 年 12 月 2 日开始,trunk 之后不再接受新的 pod 和新版本。已经发布的版本照常能 pod install,现有工程不会因此编译失败,但依赖从此拿不到更新。还在持续开发的工程,应该逐个库迁移到 Swift Package Manager(SPM):盘点 Podfile.lock,移除一个 pod,加上对应的 Swift Package,编译并真机验证后再迁下一个。下文给出常用库的 SPM 支持对照和 7 个迁移步骤。

时间和影响以 CocoaPods Trunk Read-only Plan 原文为准,下文内容截至 2026 年 10 月。

CocoaPods 只读后影响什么?

CocoaPods 博客在 2024 年 11 月 30 日公布了计划,时间表如下。

时间 事件
2025 年 5 月 新 pod 不能再使用 prepare_command 字段,已有的不受影响
2026 年 9–10 月 再次邮件通知所有发布过 Podspec 的作者
2026 年 11 月 1–7 日 进行一次只读试运行
2026 年 12 月 2 日 trunk 永久停止接受新的 Podspec

对使用 CocoaPods 的工程,影响分这几种。

情况 只读之后
pod install 已经发布过的版本 照常能装,博客说明 Specs 仓库和 CDN 会继续运行
想升级到库的新版本 库作者没法再往 trunk 发新版本,pod update 拿不到
自建 spec 仓库、:path、:git 引用的库 不经过 trunk,不受影响
依赖已经全部 vendored 进仓库 不受影响

不少库已经提前行动。Firebase 的迁移说明写明,2026 年 10 月起不再向 CocoaPods 发布新版本,CocoaPods 上的最后一个大版本是 Firebase 12,已有版本仍可安装。之后的更新要通过 SPM 或 Firebase 提供的 zip 包获取,官方首推 SPM。

哪些工程该迁移到 SPM?

你的情况 建议
还在持续开发,依赖要跟着升级 尽早迁移到 SPM,先从更新频繁的库开始
用了 Firebase 等已宣布停发 CocoaPods 的 SDK 优先迁移这些库
工程基本不再改,只偶尔出包 可以不急,锁定 Podfile.lock 照常构建
依赖里有不支持 SPM 的老库 先迁移其他库,这个库保留 pod,或者换成替代库
全是内部私有 pod、自建 spec 仓库 不受只读影响,按团队计划决定

迁移不必一次完成。CocoaPods 和 SPM 可以在同一个工程里共存,逐个库迁移、每迁一个就编译验证一次,风险最小。

常用库支持 SPM 吗?

下表是各库仓库根目录是否提供 Package.swift,以及 SPM 里的产品名。添加时用这个地址和产品名,以各库 README 为准。

库 SPM 地址 产品名 说明
Alamofire https://github.com/Alamofire/Alamofire.git Alamofire 支持
SDWebImage https://github.com/SDWebImage/SDWebImage.git SDWebImage 支持
Kingfisher https://github.com/onevcat/Kingfisher.git Kingfisher 支持
SnapKit https://github.com/SnapKit/SnapKit.git SnapKit 支持
Firebase https://github.com/firebase/firebase-ios-sdk.git FirebaseAnalytics、FirebaseMessaging、FirebaseCrashlytics、FirebaseAuth 等 支持,按用到的模块分别选产品
Lottie https://github.com/airbnb/lottie-spm.git Lottie 支持,官方建议用 lottie-spm 这个小仓库
Realm https://github.com/realm/realm-swift.git RealmSwift(Objective-C 用 Realm) 支持
RxSwift https://github.com/ReactiveX/RxSwift.git RxSwift、RxCocoa、RxRelay 支持
Moya https://github.com/Moya/Moya.git Moya、RxMoya、CombineMoya 支持,依赖 Alamofire,两者一起迁
SwiftyJSON https://github.com/SwiftyJSON/SwiftyJSON.git SwiftyJSON 支持
IQKeyboardManager https://github.com/hackiftekhar/IQKeyboardManager.git IQKeyboardManagerSwift 支持
MJRefresh https://github.com/CoderMJLee/MJRefresh.git MJRefresh 支持
MBProgressHUD https://github.com/jdg/MBProgressHUD.git MBProgressHUD 支持
SVProgressHUD https://github.com/SVProgressHUD/SVProgressHUD.git SVProgressHUD 支持
MMKV https://github.com/Tencent/MMKV.git MMKV 支持
KeychainAccess https://github.com/kishikawakatsumi/KeychainAccess.git KeychainAccess 支持
Google Sign-In https://github.com/google/GoogleSignIn-iOS.git GoogleSignIn、GoogleSignInSwift 支持
Facebook SDK https://github.com/facebook/facebook-ios-sdk.git FacebookCore、FacebookLogin、FacebookShare 等 支持
Masonry — — 仓库没有 Package.swift。Swift 工程可改用 SnapKit,或继续用 pod
AFNetworking — — 2023 年 1 月起已停止维护,建议换成 Alamofire 或 URLSession
YYModel — — 仓库没有 Package.swift,可改用 Codable,或继续用 pod

表里没有的库,打开它的 GitHub 仓库看根目录有没有 Package.swift,README 里一般也会写 SPM 的安装方法。一些国内常见的闭源 SDK 只提供 pod 或手动集成,以 SDK 官方文档为准。

怎么从 CocoaPods 迁移到 SPM?

下面以一个用 .xcworkspace 构建的 MyApp 为例,把 Alamofire 从 pod 换成 Swift Package。开始前新建一个分支,确认工程当前能编译通过。

1. 盘点依赖

打开 Podfile.lock,列出每个 pod 和当前锁定的版本,对照上一节标出哪些支持 SPM。注意 pod 之间的依赖关系,比如 Moya 依赖 Alamofire,这类要一起迁,否则同一个库会出现两份。

Podfile 里的版本写法换成 SPM 的版本规则,对应关系如下。

Podfile 含义 SPM 版本规则
pod 'Alamofire', '~> 5.9' 5.9 及以上、6.0 以下 从 5.9.0 到下一个主版本
pod 'Alamofire', '~> 5.9.1' 5.9.1 及以上、5.10 以下 从 5.9.1 到下一个次版本
pod 'Alamofire', '5.9.1' 固定这一个版本 固定 5.9.1

迁移时先用 Podfile.lock 里锁定的版本,迁移完成、编译通过后再单独升级,出问题时容易分辨原因。

2. 移除一个 pod

在 Podfile 里删掉或注释掉这一行,然后在 Podfile 所在目录重新安装。

1target 'MyApp' do
2  use_frameworks!
3  # pod 'Alamofire', '~> 5.9'
4  pod 'SDWebImage'
5end
1pod install

3. 添加 Swift Package

在 Windows、Linux、macOS 上用 KXBuild 时,以下两种做法任选其一。

  • VS Code 插件。命令面板运行 KXBuild: 添加 Swift Package 依赖…,或在 KXBuild 视图中右键 MyApp target 选择它。输入包的 Git 地址,选版本规则和产品 Alamofire。
  • 命令行。在工程目录执行下面的命令,-P 填 .xcodeproj,不是 .xcworkspace。
1kxbuild project add-package -P .\MyApp.xcodeproj -t MyApp --url https://github.com/Alamofire/Alamofire.git --from 5.9.0 --product Alamofire

固定版本用 --exact 5.9.1,到下一个次版本用 --up-to-next-minor 5.9.1,其他参数见 project add-package。添加时需要联网,产品名不对或解析失败时工程保持原样。

4. 改 import 和代码

大多数库的模块名和 pod 一样,import Alamofire、import Kingfisher 不用改。需要检查的是这几类。

  • 按模块拆分的 SDK。Firebase 这类在 SPM 里分成多个产品,按用到的产品 import,例如 import FirebaseCore、import FirebaseAnalytics。
  • 产品名不同的库。IQKeyboardManager 的产品是 IQKeyboardManagerSwift,Realm 的 Swift 接口是 RealmSwift,import 写产品对应的模块名。
  • Objective-C 头文件。#import <SDWebImage/SDWebImage.h> 一般仍可用,也可以改成 @import SDWebImage;。

改完先编译一次。Pods 目录还在时继续构建 .xcworkspace。

1kxbuild build .\MyApp.xcworkspace -D CODE_SIGNING_ALLOWED=NO

5. 处理资源 bundle

用 pod 时,有些代码按名字去 App 里找库的资源包,例如 Bundle.main.path(forResource: "XXX", ofType: "bundle")。换成 SPM 后资源包的名字和位置会变,这类代码会返回 nil,界面上图标、本地化文字消失,或者运行时崩溃。

  • 全局搜索 forResource: 和 .bundle,找出读取第三方库资源的地方。
  • 优先改用库提供的公开接口,不要自己拼资源包路径。
  • 你自己的本地包读取包内资源时用 Bundle.module,这个属性只在包的代码里能用。

6. 编译、真机验证、提交

编译通过后按 F5 装到手机,把用到这个库的功能都点一遍。启动后报 unrecognized selector 的,多半是 Objective-C 库的分类没被链接进来。CocoaPods 默认会给工程加 -ObjC,迁移后在 target 的 Other Linker Flags 里补上,用工程设置编辑器或下面的命令都行。

1kxbuild project add-setting -k OTHER_LDFLAGS -v '$(inherited),-ObjC' -a -t MyApp -P .\MyApp.xcodeproj

一切正常就提交这次改动,包括 Podfile、Podfile.lock、project.pbxproj 和 SPM 生成的 Package.resolved。然后回到第 2 步迁下一个库。

7. 最后一个 pod 迁完后

所有 pod 都换成 Swift Package 之后,再彻底移除 CocoaPods。不要提前删 Pods 和工作区,那时还有库在用它们。

  1. 在 Podfile 所在目录运行 pod deintegrate,它会从工程里移除 CocoaPods 加的构建阶段和配置。
  2. 删除 Podfile、Podfile.lock 和 Pods 目录。
  3. 工作区里只有 MyApp.xcodeproj 和 Pods 时,删掉 MyApp.xcworkspace。工作区里还有别的工程的保留。
  4. 在 KXBuild 视图把启动项目切到 MyApp.xcodeproj,构建、CI 脚本里的 .xcworkspace 也都改成 .xcodeproj。
1kxbuild build .\MyApp.xcodeproj -c Release

CI 里建议加上 --only-use-versions-from-resolved-file,严格按 Package.resolved 的版本构建,参数说明见构建与配置。

CocoaPods 和 SPM 能混用吗?

  • 同一个库只留一个来源。一个库既在 Podfile 里又加成了 Swift Package,会出现重复符号或运行时两份实例。间接依赖也算,比如 pod 里的 Moya 会带进 Alamofire。
  • 混用期间构建 .xcworkspace。Swift Package 加在 .xcodeproj 上,从工作区构建时会一起解析。
  • 每次改 Podfile 后都要 pod install,再构建。
  • 一次只迁一个库。出问题时回退一个提交就行,不用排查一堆改动。

Flutter 和 React Native 工程怎么办?

Flutter。按 Flutter 官方的 Swift Package Manager 说明,从 3.44 起 SPM 支持默认开启,升级 Flutter 后运行 App 会自动加上 SPM 集成。工程里有插件还不支持 SPM 时,Flutter 会对这些插件退回 CocoaPods,这时照常在 ios 目录运行 pod install,做法见 Flutter iOS 构建。Flutter 文档还提醒,以后将不再允许关闭 SPM,所以不要关掉它,而是把插件逐步升级到支持 SPM 的版本。

React Native 和 Expo。iOS 端目前仍通过 ios 目录的 Podfile 安装原生依赖。CocoaPods 只读后的迁移方式请关注 React Native 和 Expo 官方的进展,在官方给出方案前不要自己把 Pods 换成 Swift Package。日常构建做法见 React Native 技术栈。

常见问题

CocoaPods 只读后 pod install 还能用吗?

能用。已经发布到 trunk 的版本照常可以安装,现有工程按 Podfile.lock 构建不受影响。变化是库作者不能再往 trunk 发布新版本,你拿不到后续更新。

CocoaPods trunk 什么时候变成只读?

按 CocoaPods 官方博客的计划,2026 年 12 月 2 日永久停止接受新的 Podspec,之前的 11 月 1 日到 7 日会做一次只读试运行。

一定要把所有 pod 都换成 Swift Package 吗?

不一定。还在持续开发、需要升级依赖的库应该迁移,不再更新的老工程可以锁定 Podfile.lock 继续用。不支持 SPM 的库可以先保留 pod,两者能在同一个工程里共存。

迁移后编译报 no such module 怎么办?

先确认包已经加到正在构建的那个 target,产品名选对了,import 写的是产品对应的模块名,比如 IQKeyboardManagerSwift、FirebaseAnalytics。还在用 Pods 时要构建 .xcworkspace。仍然报错的,运行 kxbuild project resolve .\MyApp.xcworkspace --force 重新解析依赖。

Flutter 工程要自己迁移到 SPM 吗?

不用手动改。Flutter 3.44 起默认开启 SPM,升级 Flutter 后运行 App 会自动接入,插件不支持 SPM 时自动退回 CocoaPods。你要做的是把插件升级到支持 SPM 的版本。