cocoapods-to-spm
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseCocoaPods to Swift Package Manager Migration
从CocoaPods迁移至Swift Package Manager(SPM)
Step-by-step guide for migrating Capacitor iOS projects from CocoaPods to Swift Package Manager.
为Capacitor iOS项目从CocoaPods迁移至Swift Package Manager提供的分步指南。
When to Use This Skill
何时使用本指南
- User wants to migrate from CocoaPods to SPM
- User is setting up a new project with SPM
- User needs to add SPM dependencies to Capacitor
- User has CocoaPods issues and wants an alternative
- User wants faster builds (SPM often faster)
- 用户希望从CocoaPods迁移至SPM
- 用户正在使用SPM搭建新项目
- 用户需要为Capacitor添加SPM依赖项
- 用户遇到CocoaPods问题,想要寻找替代方案
- 用户希望提升构建速度(SPM通常速度更快)
Why Migrate to SPM?
为何迁移至SPM?
| Aspect | CocoaPods | SPM |
|---|---|---|
| Build Speed | Slower | Faster |
| Apple Integration | Third-party | Native Xcode |
| Ruby Dependency | Required | None |
| Version Management | Podfile.lock | Package.resolved |
| Xcodeproj Changes | Modifies project | Uses workspace |
| Binary Caching | Limited | Built-in |
| 维度 | CocoaPods | SPM |
|---|---|---|
| 构建速度 | 较慢 | 更快 |
| Apple集成 | 第三方工具 | Xcode原生支持 |
| Ruby依赖 | 必需 | 无 |
| 版本管理 | Podfile.lock | Package.resolved |
| Xcodeproj变更 | 修改项目文件 | 使用工作区 |
| 二进制缓存 | 受限 | 内置支持 |
Migration Process
迁移流程
Step 1: Analyze Current Dependencies
步骤1:分析当前依赖项
First, identify what you're currently using:
bash
cd ios/App
cat Podfile
pod outdatedCommon Capacitor pods to migrate:
ruby
undefined首先,确认当前使用的依赖:
bash
cd ios/App
cat Podfile
pod outdated常见需迁移的Capacitor Pods:
ruby
undefinedPodfile (before)
Podfile (before)
target 'App' do
capacitor_pods
pod 'Firebase/Analytics'
pod 'Firebase/Messaging'
pod 'Alamofire'
pod 'KeychainAccess'
end
undefinedtarget 'App' do
capacitor_pods
pod 'Firebase/Analytics'
pod 'Firebase/Messaging'
pod 'Alamofire'
pod 'KeychainAccess'
end
undefinedStep 2: Find SPM Equivalents
步骤2:寻找SPM替代方案
Most popular libraries support SPM. Use these URLs:
| Library | SPM URL |
|---|---|
| Firebase | |
| Alamofire | |
| KeychainAccess | |
| SDWebImage | |
| SnapKit | |
| Realm | |
| Lottie | |
大多数热门库都支持SPM。可使用以下URL:
| 库 | SPM URL |
|---|---|
| Firebase | |
| Alamofire | |
| KeychainAccess | |
| SDWebImage | |
| SnapKit | |
| Realm | |
| Lottie | |
Step 3: Clean CocoaPods
步骤3:清理CocoaPods
bash
cd ios/Appbash
cd ios/AppRemove CocoaPods integration
移除CocoaPods集成
pod deintegrate
pod deintegrate
Remove Podfile.lock and Pods directory
移除Podfile.lock和Pods目录
rm -rf Podfile.lock Pods
rm -rf Podfile.lock Pods
Remove workspace (we'll use project directly or create new workspace)
移除工作区(我们将直接使用项目或创建新工作区)
rm -rf App.xcworkspace
undefinedrm -rf App.xcworkspace
undefinedStep 4: Add SPM Dependencies in Xcode
步骤4:在Xcode中添加SPM依赖项
- Open in Xcode
ios/App/App.xcodeproj - Select the project in navigator
- Go to Package Dependencies tab
- Click + to add package
- Enter the package URL
- Choose version rules
- Select target
App
- 在Xcode中打开
ios/App/App.xcodeproj - 在导航栏中选择项目
- 进入Package Dependencies标签页
- 点击**+**添加包
- 输入包的URL
- 选择版本规则
- 选择目标
App
Step 5: Update Podfile for Capacitor Core
步骤5:为Capacitor Core更新Podfile
Capacitor still needs CocoaPods for its core. Create minimal Podfile:
ruby
undefinedCapacitor核心仍需依赖CocoaPods。创建极简Podfile:
ruby
undefinedios/App/Podfile
ios/App/Podfile
require_relative '../../node_modules/@capacitor/ios/scripts/pods_helpers'
platform :ios, '14.0'
use_frameworks!
install! 'cocoapods', :disable_input_output_paths => true
def capacitor_pods
pod 'Capacitor', :path => '../../node_modules/@capacitor/ios'
pod 'CapacitorCordova', :path => '../../node_modules/@capacitor/ios'
end
target 'App' do
capacitor_pods
Other plugin pods that don't support SPM yet
end
post_install do |installer|
assertDeploymentTarget(installer)
end
Then run:
```bash
cd ios/App && pod installrequire_relative '../../node_modules/@capacitor/ios/scripts/pods_helpers'
platform :ios, '14.0'
use_frameworks!
install! 'cocoapods', :disable_input_output_paths => true
def capacitor_pods
pod 'Capacitor', :path => '../../node_modules/@capacitor/ios'
pod 'CapacitorCordova', :path => '../../node_modules/@capacitor/ios'
end
target 'App' do
capacitor_pods
其他暂不支持SPM的插件Pods
end
post_install do |installer|
assertDeploymentTarget(installer)
end
然后运行:
```bash
cd ios/App && pod installStep 6: Configure Plugin for SPM Support
步骤6:配置插件以支持SPM
If you're creating a Capacitor plugin with SPM support:
Package.swift:
swift
// swift-tools-version: 5.9
import PackageDescription
let package = Package(
name: "CapacitorNativeBiometric",
platforms: [.iOS(.v14)],
products: [
.library(
name: "CapacitorNativeBiometric",
targets: ["NativeBiometricPlugin"]
),
],
dependencies: [
.package(url: "https://github.com/nicholasalx/capacitor-swift-pm", from: "6.0.0"),
],
targets: [
.target(
name: "NativeBiometricPlugin",
dependencies: [
.product(name: "Capacitor", package: "capacitor-swift-pm"),
.product(name: "Cordova", package: "capacitor-swift-pm"),
],
path: "ios/Sources/NativeBiometricPlugin",
publicHeadersPath: "include"
),
]
)如果你正在创建支持SPM的Capacitor插件:
Package.swift:
swift
// swift-tools-version: 5.9
import PackageDescription
let package = Package(
name: "CapacitorNativeBiometric",
platforms: [.iOS(.v14)],
products: [
.library(
name: "CapacitorNativeBiometric",
targets: ["NativeBiometricPlugin"]
),
],
dependencies: [
.package(url: "https://github.com/nicholasalx/capacitor-swift-pm", from: "6.0.0"),
],
targets: [
.target(
name: "NativeBiometricPlugin",
dependencies: [
.product(name: "Capacitor", package: "capacitor-swift-pm"),
.product(name: "Cordova", package: "capacitor-swift-pm"),
],
path: "ios/Sources/NativeBiometricPlugin",
publicHeadersPath: "include"
),
]
)Step 7: Xcode Project Structure for SPM
步骤7:SPM的Xcode项目结构
ios/
├── App/
│ ├── App/
│ │ ├── AppDelegate.swift
│ │ ├── Info.plist
│ │ └── ...
│ ├── App.xcodeproj/
│ │ └── project.xcworkspace/
│ │ └── xcshareddata/
│ │ └── swiftpm/
│ │ └── Package.resolved # SPM lock file
│ ├── Podfile
│ └── Podfile.lock
└── ...ios/
├── App/
│ ├── App/
│ │ ├── AppDelegate.swift
│ │ ├── Info.plist
│ │ └── ...
│ ├── App.xcodeproj/
│ │ └── project.xcworkspace/
│ │ └── xcshareddata/
│ │ └── swiftpm/
│ │ └── Package.resolved # SPM锁定文件
│ ├── Podfile
│ └── Podfile.lock
└── ...Hybrid Approach (Recommended)
混合方案(推荐)
Most Capacitor projects work best with a hybrid approach:
大多数Capacitor项目使用混合方案效果最佳:
Keep in CocoaPods:
保留在CocoaPods中的内容:
- core
@capacitor/ios - Capacitor plugins without SPM support
- 核心库
@capacitor/ios - 暂不支持SPM的Capacitor插件
Move to SPM:
迁移至SPM的内容:
- Firebase
- Third-party libraries
- Your own Swift packages
- Firebase
- 第三方库
- 自定义Swift包
Example Hybrid Setup
混合方案示例
Podfile:
ruby
require_relative '../../node_modules/@capacitor/ios/scripts/pods_helpers'
platform :ios, '14.0'
use_frameworks!
install! 'cocoapods', :disable_input_output_paths => true
def capacitor_pods
pod 'Capacitor', :path => '../../node_modules/@capacitor/ios'
pod 'CapacitorCordova', :path => '../../node_modules/@capacitor/ios'
# Plugins without SPM support
pod 'CapacitorCamera', :path => '../../node_modules/@capacitor/camera'
end
target 'App' do
capacitor_pods
# NO Firebase here - use SPM instead
endXcode Package Dependencies:
- Firebase iOS SDK
- Any other SPM-compatible libraries
Podfile:
ruby
require_relative '../../node_modules/@capacitor/ios/scripts/pods_helpers'
platform :ios, '14.0'
use_frameworks!
install! 'cocoapods', :disable_input_output_paths => true
def capacitor_pods
pod 'Capacitor', :path => '../../node_modules/@capacitor/ios'
pod 'CapacitorCordova', :path => '../../node_modules/@capacitor/ios'
# 暂不支持SPM的插件
pod 'CapacitorCamera', :path => '../../node_modules/@capacitor/camera'
end
target 'App' do
capacitor_pods
# 此处不添加Firebase - 改用SPM
endXcode包依赖项:
- Firebase iOS SDK
- 其他支持SPM的库
Common Issues and Solutions
常见问题及解决方案
Issue: Duplicate Symbols
问题:重复符号
Cause: Same library in both CocoaPods and SPM
Solution: Remove from Podfile if using SPM
ruby
undefined原因:同一库同时存在于CocoaPods和SPM中
解决方案:如果使用SPM,从Podfile中移除该库
ruby
undefinedPodfile - WRONG
Podfile - 错误写法
pod 'Firebase/Analytics' # Remove this
pod 'Firebase/Analytics' # 移除这一行
Use SPM instead in Xcode
改用Xcode中的SPM添加
undefinedundefinedIssue: Module Not Found
问题:模块未找到
Cause: SPM package not linked to target
Solution:
- Xcode > Project > Targets > App
- General > Frameworks, Libraries, and Embedded Content
- Add the SPM package product
原因:SPM包未关联至目标
解决方案:
- Xcode > 项目 > 目标 > App
- 常规 > 框架、库和嵌入式内容
- 添加SPM包产物
Issue: Build Errors After Migration
问题:迁移后出现构建错误
Cause: Missing frameworks or wrong imports
Solution: Clean and rebuild
bash
undefined原因:缺少框架或导入错误
解决方案:清理并重新构建
bash
undefinedClean derived data
清理派生数据
rm -rf ~/Library/Developer/Xcode/DerivedData
rm -rf ~/Library/Developer/Xcode/DerivedData
Clean build folder in Xcode
在Xcode中清理构建文件夹
Cmd + Shift + K
Cmd + Shift + K
Rebuild
重新构建
bunx cap sync ios
cd ios/App && pod install
undefinedbunx cap sync ios
cd ios/App && pod install
undefinedIssue: Capacitor Plugin Not Found
问题:Capacitor插件未找到
Cause: Plugin needs registration
Solution: Ensure plugin is registered in :
AppDelegate.swiftswift
import Capacitor
import YourPlugin
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
// Capacitor handles plugin registration automatically
return true
}
}原因:插件未注册
解决方案:确保插件已在中注册:
AppDelegate.swiftswift
import Capacitor
import YourPlugin
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
// Capacitor会自动处理插件注册
return true
}
}Creating SPM-Compatible Capacitor Plugin
创建支持SPM的Capacitor插件
Directory Structure
目录结构
my-capacitor-plugin/
├── Package.swift
├── ios/
│ └── Sources/
│ └── MyPlugin/
│ ├── MyPlugin.swift
│ ├── MyPlugin.m # Objc bridge if needed
│ └── include/
│ └── MyPlugin.h # Public headers
├── src/
│ ├── index.ts
│ ├── definitions.ts
│ └── web.ts
└── package.jsonmy-capacitor-plugin/
├── Package.swift
├── ios/
│ └── Sources/
│ └── MyPlugin/
│ ├── MyPlugin.swift
│ ├── MyPlugin.m # 如需Objective-C桥接文件
│ └── include/
│ └── MyPlugin.h # 公开头文件
├── src/
│ ├── index.ts
│ ├── definitions.ts
│ └── web.ts
└── package.jsonPackage.swift Template
Package.swift模板
swift
// swift-tools-version: 5.9
import PackageDescription
let package = Package(
name: "CapacitorMyPlugin",
platforms: [.iOS(.v14)],
products: [
.library(
name: "CapacitorMyPlugin",
targets: ["MyPluginPlugin"]
),
],
dependencies: [
.package(url: "https://github.com/nicholasalx/capacitor-swift-pm", from: "6.0.0"),
],
targets: [
.target(
name: "MyPluginPlugin",
dependencies: [
.product(name: "Capacitor", package: "capacitor-swift-pm"),
.product(name: "Cordova", package: "capacitor-swift-pm"),
],
path: "ios/Sources/MyPlugin"
),
]
)swift
// swift-tools-version: 5.9
import PackageDescription
let package = Package(
name: "CapacitorMyPlugin",
platforms: [.iOS(.v14)],
products: [
.library(
name: "CapacitorMyPlugin",
targets: ["MyPluginPlugin"]
),
],
dependencies: [
.package(url: "https://github.com/nicholasalx/capacitor-swift-pm", from: "6.0.0"),
],
targets: [
.target(
name: "MyPluginPlugin",
dependencies: [
.product(name: "Capacitor", package: "capacitor-swift-pm"),
.product(name: "Cordova", package: "capacitor-swift-pm"),
],
path: "ios/Sources/MyPlugin"
),
]
)Plugin Swift Code
插件Swift代码
swift
import Foundation
import Capacitor
@objc(MyPlugin)
public class MyPlugin: CAPPlugin, CAPBridgedPlugin {
public let identifier = "MyPlugin"
public let jsName = "MyPlugin"
public let pluginMethods: [CAPPluginMethod] = [
CAPPluginMethod(name: "echo", returnType: CAPPluginReturnPromise),
]
@objc func echo(_ call: CAPPluginCall) {
let value = call.getString("value") ?? ""
call.resolve(["value": value])
}
}swift
import Foundation
import Capacitor
@objc(MyPlugin)
public class MyPlugin: CAPPlugin, CAPBridgedPlugin {
public let identifier = "MyPlugin"
public let jsName = "MyPlugin"
public let pluginMethods: [CAPPluginMethod] = [
CAPPluginMethod(name: "echo", returnType: CAPPluginReturnPromise),
]
@objc func echo(_ call: CAPPluginCall) {
let value = call.getString("value") ?? ""
call.resolve(["value": value])
}
}Migration Checklist
迁移检查清单
- List all current CocoaPods dependencies
- Identify SPM equivalents for each
- Run
pod deintegrate - Add SPM packages in Xcode
- Create minimal Podfile for Capacitor core
- Run
pod install - Clean derived data
- Build and test
- Commit to git
Package.resolved - Update CI/CD scripts if needed
- 列出所有当前CocoaPods依赖项
- 为每个依赖项找到SPM替代方案
- 运行
pod deintegrate - 在Xcode中添加SPM包
- 为Capacitor核心创建极简Podfile
- 运行
pod install - 清理派生数据
- 构建并测试
- 将提交至git
Package.resolved - 如有需要,更新CI/CD脚本
Resources
资源
- Swift Package Manager Documentation: https://swift.org/package-manager
- Capacitor iOS Documentation: https://capacitorjs.com/docs/ios
- CocoaPods to SPM Migration: https://developer.apple.com/documentation/xcode/adding-package-dependencies-to-your-app
- Swift Package Manager文档:https://swift.org/package-manager
- Capacitor iOS文档:https://capacitorjs.com/docs/ios
- CocoaPods转SPM迁移:https://developer.apple.com/documentation/xcode/adding-package-dependencies-to-your-app