关于 cocoapods-to-spm
面向 Capacitor iOS 应用从 CocoaPods 迁移到 Swift Package Manager 的技能,重点是在迁移时保留原生项目定制。它指导开发者检查依赖、选择迁移方式并验证结果。
主要功能
- 01检查依赖与项目定制
- 02核对插件的 SPM 兼容性
- 03选择迁移路径
- 04提供 CLI 和 Xcode 操作步骤
- 05验证迁移结果
- 06排查常见迁移故障
适用场景
- 01将现有 Capacitor iOS 应用迁移到 SPM
- 02找出阻碍迁移的插件或 Pod
- 03保留扩展和原生项目设置
- 04诊断迁移后缺失的插件
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ cap-go/ capgo-skills --skill cocoapods-to-spm安装后在 Claude Code 中输入/cocoapods-to-spm确认已加载。
附带文件metadata.jsonreferences/troubleshooting.md
详细介绍
从 CocoaPods 迁移到 Swift Package Manager
将 Capacitor iOS 应用从 CocoaPods 迁移到 SPM,同时保留原生项目自定义配置。
适用场景
在以下情况下触发:
- 存在
ios/App/Podfile、Pods/、Podfile.lock或App.xcworkspace,且用户想要使用 SPM。 - 用户询问
npx cap spm-migration-assistant、CapApp-SPM、debug.xcconfig或--packagemanager SPM。 - 用户担心 CocoaPods Trunk 将变为只读(预计于 2026 年 12 月 2 日),或担心某些 Pod 将无法再发布或更新。
npx cap sync警告Some installed Capacitor plugins are not compatible with SPM或<plugin id> does not have a Package.swift。- 升级到 Capacitor 9 时,用户也想同时弃用 CocoaPods。
请勿用于:
- 为你维护的插件添加
Package.swift/CAPBridgedPlugin→capacitor-plugin-spm-support。 - 采用 SceneDelegate / UIScene(Capacitor 8.5+,Xcode 27 要求)→
capacitor-uiscene-migration。 - Capacitor 主版本升级本身 →
capacitor-app-upgrades、capacitor-app-upgrade-v8-to-v9。 - 与依赖管理无关的构建或运行时故障 →
debugging-capacitor。
为什么现在迁移
- CocoaPods Trunk 预计将于 2026 年 12 月 2 日变为只读。现有 Pod 仍可解析,但不会再发布新版本,因此插件修复将越来越多地仅通过 SPM 发布。
- Capacitor 8+ 默认使用 SPM 搭建新的 iOS 项目。升级 Capacitor 不会将现有的 CocoaPods 应用转换为 SPM。
- Capacitor 9(目前为
next/ alpha)只有在安装了 Cordova 插件时,才会添加Cordova产品 /CapacitorCordovaPod。未安装 Cordova 插件却导入Cordova的原生代码,在两种配置中都会出错。
CLI 如何判断
- 当且仅当
ios/App/CapApp-SPM/存在时,CLI 才会将项目视为使用 SPM。删除或重命名该目录会悄无声息地使npx cap sync恢复为 CocoaPods 行为。 - 每次运行
npx cap sync ios都会重新生成ios/App/CapApp-SPM/Package.swift(// DO NOT MODIFY THIS FILE - managed by Capacitor CLI commands)。请在capacitor.config.*中进行自定义,切勿修改该文件。 - 只有当插件的 npm 包根目录中包含
Package.swift时,才会纳入该插件。其他插件会被跳过并显示警告;其原生代码会在运行时悄无声息地缺失("X" plugin is not implemented on ios)。 - 同步期间,如果插件的
Package.swift将capacitor-swift-pm固定到不同的主版本,CLI 会重写node_modules中的该文件,并警告<id> is built for Capacitor <N>, it might cause issues。请将此视为“升级插件”的提示,而非成功。 - Cordova 插件会在
ios/capacitor-cordova-ios-plugins/sources/<Name>下生成一个包。SPM 二进制目标不支持普通的.framework文件(警告:custom .framework files are not supported as binaryTarget in SPM);这些文件需要转换为.xcframework。
命令策略
- 安装依赖和运行脚本时使用仓库的包管理器;调用 Capacitor CLI 时使用
npx cap ...,以确保运行项目本地的 CLI。 - 请从包含
capacitor.config.*的目录运行命令。
实时项目快照
检测到的 Capacitor、iOS、Cordova 和插件依赖:
!node -e "const fs=require('fs');if(!fs.existsSync('package.json'))process.exit(0);const pkg=JSON.parse(fs.readFileSync('package.json','utf8'));const out=[];for(const section of ['dependencies','devDependencies']){for(const [name,version] of Object.entries(pkg[section]||{})){if(name.startsWith('@capacitor/')||name.startsWith('@capgo/')||name.startsWith('@capacitor-community/')||name.startsWith('@awesome-cordova-plugins/')||name.startsWith('cordova-')||name.includes('capacitor'))out.push(section+'.'+name+'='+version)}}console.log(out.sort().join('\n'))"
相关 iOS 依赖文件:
!find ios -maxdepth 5 \( -name 'Podfile' -o -name 'Podfile.lock' -o -name 'Pods' -o -name 'App.xcworkspace' -o -name 'Package.swift' -o -name 'Package.resolved' -o -name 'CapApp-SPM' -o -name 'debug.xcconfig' -o -name 'project.pbxproj' -o -name 'Info.plist' -o -name '*.entitlements' -o -name 'GoogleService-Info.plist' \) 2>/dev/null
流程
1. 检查(只读)
- 查看
package.json中的 Capacitor 版本(@capacitor/ios)。支持 8.x 和 9.x;如果是 6.x/7.x,建议先升级。 - 检查
ios/App/Podfile和Podfile.lock:列出所有 pod,以及哪些不是 Capacitor 插件(Firebase、分析 SDK、手动添加的自定义 pod)。 - 对于每个 Capacitor/Cordova 插件:
node_modules/<pkg>/Package.swift是否存在?Cordova 插件会生成对应的包,因此只有NO项会造成阻碍:node -e "const fs=require('fs');const p=require('./package.json');for(const n of Object.keys({...p.dependencies,...p.devDependencies})){const d='node_modules/'+n;if(!fs.existsSync(d+'/ios')&&!fs.existsSync(d+'/plugin.xml'))continue;console.log((fs.existsSync(d+'/Package.swift')?'SPM ':fs.existsSync(d+'/plugin.xml')?'CORDOVA ':'NO ')+n)}" - 检查
ios/App/App.xcodeproj/project.pbxproj:签名、自定义构建设置、额外目标(小组件、通知服务扩展)、构建阶段、方案。 - 检查
ios/App/App/:AppDelegate.swift、SceneDelegate.swift、Info.plist、entitlements、GoogleService-Info.plist、自定义 Swift/ObjC 文件。
编辑前先报告检查结果:没有 SPM 支持的插件、需要 SPM 替代方案的非插件 pod,以及可能受影响的原生自定义内容。
2. 解决阻碍
对于每个 NO 插件或非插件 pod:
- 升级插件(大多数维护中的插件,包括
@capacitor/*和@capgo/*,都附带Package.swift)。 - 替换为维护良好且支持 SPM 的替代方案。
- 如果项目由你维护该插件,可使用
capacitor-plugin-spm-support转换。 - 对于直接添加到 Podfile 的第三方 SDK pod,在迁移后将供应商的 SPM 包添加到 Xcode 中的 App 目标。
如果关键插件没有 SPM 迁移路径,请先询问用户再继续。不要保留混合使用 Podfile 和 CapApp-SPM 的配置。
3. 选择路径
| 路径 | 适用情况 |
|---|---|
npx cap spm-migration-assistant | 适用于大多数应用;保留现有 Xcode 项目及其自定义内容。 |
| 全新脚手架 | ios/ 与模板接近(没有扩展,原生修改较少)。 |
| 手动修复 | 助手仅部分运行成功,或项目经过大量自定义。 |
4a. 运行迁移助手
先提交更改。仍需安装 CocoaPods(或 Bundler),因为迁移会运行 pod deintegrate。
npx cap spm-migration-assistant
迁移助手会运行 pod deintegrate,删除 Podfile、Podfile.lock 和 App.xcworkspace,提取 ios/App/CapApp-SPM/,写入 ios/debug.xcconfig(CAPACITOR_DEBUG = true),并在 Info.plist 中缺少 CAPACITOR_DEBUG = $(CAPACITOR_DEBUG) 时将其添加,然后运行 iOS 更新以生成 Package.swift。最后会显示 To complete migration follow the manual steps at https://capacitorjs.com/docs/ios/spm#using-our-migration-tool。
还需在 Xcode 中手动完成两个步骤(npx cap open ios 现在会打开 App.xcodeproj):
- 项目
App-> Package Dependencies ->+-> Add Local... -> 选择ios/App/CapApp-SPM-> Add Package,并将CapApp-SPM库关联到App目标。 - 项目
App-> Info -> Configurations -> Debug -> 将配置文件设为debug.xcconfig。
然后运行 npx cap sync ios。
4b. 全新脚手架
先备份第 1.5 步中列出的所有内容。
rm -rf ios
npx cap add ios --packagemanager SPM
npx cap sync ios
在 Capacitor 8.5+ 中,新模板已包含 SceneDelegate.swift 和 UIApplicationSceneManifest。通过合并而非覆盖模板文件,恢复图标、Info.plist 键、权利文件、签名配置、Firebase plist、自定义源文件和扩展目标。
5. capacitor.config.* 中的可选 SPM 配置
仅在需要时配置(均位于 experimental.ios.spm 下,并确认已安装的 CLI 版本支持这些选项):
swiftToolsVersion(8.3+,默认为'5.9'):生成的Package.swift的头部。packageTraits(8.3+):{ "<plugin id>": ["TraitName", ".defaults"] };要求swiftToolsVersion>='6.1'。packageOptions(8.4+):{ "<plugin id>": { symlink: true, moduleAliases: { "Target": "Alias" } } },用于处理软件包名称或模块冲突。
6. UIScene 检查
助手只会更改依赖管理。如果 Info.plist 中缺少 UIApplicationSceneManifest,则应用尚未使用 Capacitor 8.5+ 和 Xcode 27 要求的场景生命周期;请运行 npx cap migrate,或遵循 capacitor-uiscene-migration 中的说明。
验证
# No CocoaPods leftovers
ls ios/App | grep -E 'Podfile|Pods|xcworkspace' && echo "LEFTOVERS" || echo "clean"
# CLI sees SPM and every plugin is included
npx cap sync ios 2>&1 | grep -Ei 'Package.swift|not compatible|built for Capacitor'
grep -c '.package(name:' ios/App/CapApp-SPM/Package.swift
# Plugin classes registered for runtime
node -e "console.log(require('./ios/App/App/capacitor.config.json').packageClassList)"
# Build without Xcode UI (project, not workspace)
xcodebuild -project ios/App/App.xcodeproj -scheme App -destination 'generic/platform=iOS Simulator' build
还请在 Xcode 中确认:CapApp-SPM 已关联到 App 目标,Debug 使用 debug.xcconfig,签名、Bundle ID 和功能未发生变化。在设备上,至少运行一次每个原生插件(相机、推送、购买等)。
提交 ios/App/CapApp-SPM/ 和 ios/debug.xcconfig。对于 Package.resolved,请遵循 CapApp-SPM/.gitignore 中的规则(较新的模板会忽略它)。
错误处理
加载 references/troubleshooting.md 查看完整表格。最常见的问题:
| 消息 / 症状 | 修复方法 |
|---|---|
Capacitor project is already using SPM, exiting. | CapApp-SPM/ 已存在。请手动修复,不要使用助手。 |
CocoaPods is not installed.(助手) | 暂时安装 CocoaPods,或使用全新脚手架方案。 |
<id> does not have a Package.swift / Some installed Capacitor plugins are not compatible with SPM | 升级、替换或转换该插件(第 2 步)。 |
运行时出现 "X" plugin is not implemented on ios | 插件被跳过,未加入 Package.swift,或缺少 packageClassList。修复插件、重新同步并清理构建。 |
No such module 'Capacitor' / Missing package product 'CapApp-SPM' | 尚未添加或关联本地软件包;重新执行手动步骤 1,然后选择 File -> Packages -> Reset Package Caches。 |
| 仅 Debug 模式下功能不可用(无法检查 WebView、没有调试日志) | 未在 Debug 配置中设置 debug.xcconfig。 |
输出格式
规划时,请返回:当前状态(Capacitor 版本、pods、没有 SPM 的插件、面临风险的自定义配置)、选择的方案及原因、按顺序排列的步骤,以及仍需在 Xcode 或设备上执行的检查。