再见吧CocoaPods,Swift Package Manager(SPM)即将在Flutter 3.44中成为默认依赖管理器
长久以来Futter一直以CocoaPods为作为默认的依赖管理器,而最近就在临近Google I/O了,Flutter官方却突然宣布,从下一个Flutter稳定版3.44开始,Swift Package Manager(SPM)取代CocoaPods,成为iOS和macOS应用的默认依赖管理器。
这意味你不必再为了跑通一个App而去一顿瞎折腾Ruby环境或者安装那个令人抓狂的CocoaPods了。
Flutter这么做一方面是因为SPM是Apple官方的依赖管理器,另一方面CocoaPods实际上早进入了**维护模式,并且CocoaPods trunk 明确会在 2026-12-02 进入只读**,所以今年年底 SwiftPM 就势必会完全取代 CocoaPods 这个老古董。
终于不用再忍受那蜗牛般的pod install了……
当然这个并不突然,毕竟Flutter 支持SPM这个事早就开始实施了,我自己的项目也早早已开启了SPM模式。前段时间,我自己的开源项目还收到了支持SPM的催更请求:
![]()
现在 Flutter 也开始正式提醒开发者,虽然现有版本还可以继续使用 CocoaPods,但是 2026-12-02 之后将不会在对 Pod 进行适配和支持 pod。
那这对我们会有什么影响吗?
App 开发者
实际上,对于App开发者来说,Flutter的CLI会帮助你自动完成迁移处理。当你开始运行或构建 iOS 或 macOS 应用时,CLI 会自动更新 Xcode 项目使用全新的 Swift 包管理器。
如果 App 依赖的插件还没适配 SwiftPM,Flutter 会打印一条警告信息,列出所有不受支持的依赖项,同时暂时回退到 CocoaPods。
当然这种回退并不会长久,毕竟Cocoapods都即将寿终正寝了,SPM又是Apple的太子,对Cocoapods的支持完全移除也在情理之中了。
当然,如果你真的遇到了SPM导致的构建问题,官方也提供了临时解决方案:
flutter:
config:
enable-swift-package-manager: false
在
pubspec.yaml中把SPM关掉就好了。
插件开发者
对于插件开发者,如果你的插件支持iOS/macOS,那你是逃不开了(我不会告诉你fluwx/tobias spm适配进展缓慢)。Flutter社区其实一直在推进插件对SPM的适配(比如我就收到了适配请求),目前排名前 100 的 iOS 插件里已经有 61% 完成了迁移,后续如果没添加 Swift Package Manager 支持的 Package ,在 pub.dev 评分中得分也会被拉低。
其实是SPM与CocoaPods是非常非常不同的,这也是导致Fluwx/Tobias等项目的SPM支持进展缓慢的原因,比如说在使用CocoaPods时,podspec可以在pod install的时候作为Ruby脚本执行,即可以入侵你的Flutter项目构建过程,fluwx中的no_pay就是基于该原理实现的。而SPM虽然也是可执行的 Swift 脚本,但 SPM 在 swift package resolve 阶段就锁定了依赖图,这个阶段与 Flutter 构建流程完全解耦,无法可靠地从外部注入状态,这就导致我们无法像cocoapods那样通过在pubspec.yaml切换到no_pay状态,这意味我们又要把fluwx拆分成双包即fluwx和fluwx_no_pay。
且不提我的项目问题,说回SPM和CocoaPods的迁移问题。
具体怎么迁移,大家可以参考Flutter migration docs for plugin authors对插件进行迁移与适配。
过往的Cocoapods就像我上面说的一样,Cocoapods已经为我们做很多了隐式的骚操作,比如:
- 自动把
Flutter.framework加进来 - 自动处理 header / linker / search path
- 不用关心 Flutter 引擎怎么进来的
但换成SwiftPM后就不一样了:
- SwiftPM 是完全声明式依赖系统
- 不会有 CocoaPods 那种“魔法注入”
- 所有依赖都必须在
Package.swift明确写出来
要知道,我们的插件代码其实是运行在 Flutter 引擎之上的,所以你需要在 Package.swift 里加这个依赖,以我正在迁移的Fluwx的Package.swift为例:
// swift-tools-version: 5.9
import PackageDescription
let package = Package(
name: "fluwx",
platforms: [.iOS("12.0")],
products: [
.library(name: "fluwx", targets: ["fluwx"])
],
dependencies: [
// 这是关键
.package(name: "FlutterFramework", path: "../FlutterFramework"),
.package(
url: "https://github.com/JarvanMo/WechatOpenSDK-SPM", //
from: "2.0.5"
)
],
targets: [
.target(
name: "fluwx",
dependencies: [
// 这是关键
.product(name: "FlutterFramework", package: "FlutterFramework"),
.product(name: "WechatOpenSDK", package: "WechatOpenSDK-SPM")
],
resources: [
.process("Resources/PrivacyInfo.xcprivacy")
],
cSettings: [
.define("FLUWX_WITH_PAY"),
.headerSearchPath("include")
],
swiftSettings: [
.define("FLUWX_WITH_PAY")
],
linkerSettings: [
.linkedFramework("CoreGraphics"),
.linkedFramework("Security"),
.linkedFramework("WebKit"),
.unsafeFlags(["-ObjC", "-all_load"])
]
)
]
)
另外如果在 2025 年做过迁移了插件,现在还也需要补充一个操作:在
Package.swift文件中添加 FlutterFramework 作为依赖项,因为现在必须显式声明依赖。
从Flutter 3.41开始,要把FlutterFramework作为一个依赖:
更新一下Package.swift以引入FlutterFramework:
dependencies: [
.package(name: "FlutterFramework", path: "../FlutterFramework")
],
targets: [
.target(
// TODO: Update your target name.
name: "plugin_name",
dependencies: [
.product(name: "FlutterFramework", package: "FlutterFramework")
],
别忘记更新 Dart/Flutter 版本
environment:
sdk: ^3.11.0
flutter: ">=3.41.0"
以我的切身体验来说,对 Flutter 来说这次变化影响最大的是插件生态。以前Flutter插件都是.podspec + Podfile + pod install接入,而且有不少插件会使用到魔法注入,但迁移到SPM后,这种魔法不复存在,会使一些插件的迁移难度增加。
SPM也是完全支持Objective-C 的,只是一些支持的力度和方式不太一样,比如 SwiftPM 不允许同一个 target 里同时混放 Swift 和 C-family 源码,target 可以包含 Swift、Objective-C/C++ 或 C/C++,但单个 target 不能混合 Swift 和 C-family 语言。
旧的纯OC插件/库迁移到SPM是完全可行的,只要目录结构要符合SPM规则。
真正麻烦的是那些OC+Swift混编的工程,通常来说他们要拆成多个target……
题外话
fluwx/tobais迁移到SPM的工作还在进行中, 主要就是iOS的变动,现在没了动态化的支持,很多功能变得比较麻烦。
![]()
如果大家对插件中引用本地framework可以参考我之前的文章。
那么,你准备好迎接Swift Package Manager了吗?