再见吧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导致的构建问题,官方也提供了临时解决方案:

yaml 复制代码
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拆分成双包即fluwxfluwx_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为例:

less 复制代码
// 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:

swift 复制代码
dependencies: [
    .package(name: "FlutterFramework", path: "../FlutterFramework")
],
targets: [
    .target(
        // TODO: Update your target name.
        name: "plugin_name",
        dependencies: [
            .product(name: "FlutterFramework", package: "FlutterFramework")
        ],

别忘记更新 Dart/Flutter 版本

yaml 复制代码
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了吗?

相关推荐
mldong3 小时前
你的 Vue3 项目也能有钉钉同款审批流设计器:npm 装包,10 分钟画出第一条审批流
前端·vue.js
2分钟速写快排3 小时前
什么是 RAG?如何用 RAG 实现一个用户记忆?
前端·后端·ai编程
passerby60614 小时前
如何自己造一个时间处理库
前端·javascript·github
走到天涯海角5 小时前
react里面的长列表渲染优化
前端·react.js·前端框架
小羊没烦恼!5 小时前
Hello Web API系列教程——Web API与国际化
java·服务器·前端·javascript·php
北岛贰5 小时前
迷茫焦虑期,我做了一个带支付带官网的 AI 聊天虚拟恋人 App
前端·人工智能·后端
mayaairi7 小时前
Vue2 组件通讯(三):全局事件总线、PubSub、插槽与组件实例属性
前端·javascript·vue.js
kyriewen7 小时前
面试官问我:AI 都能写代码了,前端凭什么还值 25K
前端·javascript·人工智能
风骏时光牛马8 小时前
AI源码分析:拆解模型底层实现逻辑
前端
IT_陈寒8 小时前
React子组件莫名其妙重渲染?你可能漏了这个Hook
前端·人工智能·后端