Flutter’s Swift Package Manager Migration Is Here — And If You Maintain a Plugin, You Need to Read This 📦
“CocoaPods is in maintenance mode. The registry goes read-only in December. And Flutter already switched the default in 3.44. The clock is running.”

I maintain a few Flutter plugins myself, though none of them are heavily affected by this particular migration — my plugins don’t lean on CocoaPods-heavy native dependencies, so the transition is relatively smooth on my end. But I’ve been watching this migration ripple across the ecosystem, talking to maintainers who are in deeper, and wanted to write up exactly what’s happening, why the deadline actually matters, and what it means for the maintainers whose plugins are more entangled in the CocoaPods world than mine are.
The full picture is more interesting than “just migrate to SPM.” It’s a story about CocoaPods quietly dying, Apple doubling down on its own tooling, and a community of maintainers being handed an important migration with a hard deadline attached.
How We Got Here — The CocoaPods Story 📖
“A dependency manager that’s been around since 2011 doesn’t just stop working overnight. But maintenance mode has a way of becoming end-of-life faster than people expect.”
CocoaPods has been the de facto iOS dependency manager for over a decade. If you’ve shipped a Flutter app to iOS, you’ve used it. Every pod install, every Podfile.lock checked into version control, every time you ran arch -x86_64 pod install on an M1 Mac because something was broken — that was CocoaPods.
It’s been in maintenance mode for a while now, which in practice meant: existing packages still work, but the ecosystem isn’t growing. The team behind it stopped taking new feature requests. And now there’s a hard, non-negotiable deadline: the CocoaPods registry permanently becomes read-only on December 2, 2026. After that date, no new versions of any pod can be published to trunk. Ever.
That’s the actual forcing function. Not “SPM is better” (though it arguably is). Not “Apple prefers it” (though they clearly do). It’s that the place where CocoaPods packages live is closing its doors to new content in about two months from when I’m writing this.
What Flutter Did About It — And When 🔄
“Flutter didn’t wait for the deadline. They moved earlier than most people noticed.”
As of the 3.44 release, Flutter uses Swift Package Manager to manage iOS and macOS native dependencies. That’s not “you can opt into SPM.” That’s “SPM is now the default, and CocoaPods is the fallback.”
The timeline matters here:
- Flutter 3.24 (late 2024) — SPM support introduced behind a feature flag
- Flutter 3.44 (May 2026) — SPM becomes the default for all new Flutter apps
- December 2, 2026 — CocoaPods registry goes permanently read-only
Flutter continues to support CocoaPods in maintenance mode. Flutter falls back to CocoaPods for dependencies that don’t support Swift Package Manager yet. So nothing breaks immediately — the fallback exists precisely to avoid that. But every plugin that hasn’t migrated is now a plugin running on borrowed time, because the fallback runs CocoaPods, and CocoaPods stops getting new packages in December.
What Actually Changes in How Flutter Handles Dependencies ⚙️
“The file structure changes. The way Xcode sees your plugin changes. But the actual migration is less scary than it sounds.”
Before SPM, a Flutter plugin’s iOS native code lived in a Classes/ directory, and CocoaPods knew how to find it via the .podspec file. After SPM, the structure looks like this:
ios/
Sources/
YourPlugin/ ← source files move here
YourPlugin.swift
YourPlugin.m ← ObjC still works, just new location
Package.swift ← new file, SPM's equivalent of podspec
YourPlugin.podspec ← stays, for backward compatibility
The Package.swift is the new piece — it's SPM's manifest file, and it's where you declare your package name, Swift tools version, supported platforms, source locations, and dependencies. A minimal one looks like:
// swift-tools-version: 5.9
import PackageDescription
let package = Package(
name: "your_plugin",
platforms: [
.iOS(.v12),
],
products: [
.library(name: "your-plugin", targets: ["your_plugin"])
],
dependencies: [],
targets: [
.target(
name: "your_plugin",
dependencies: [],
path: "Sources/your_plugin"
)
]
)
Flutter plugins should support both Swift Package Manager and CocoaPods until further notice. You don’t drop the .podspec. You add the Package.swift alongside it, and Flutter intelligently routes depending on which the consuming project supports.
One detail that caught people who migrated early: if you already migrated your plugin during the 2025 pilot, you need to complete one new step — you must add FlutterFramework as a dependency in your Package.swift file. If you migrated before Flutter 3.44, there’s one more thing to add before you’re fully compliant with the current spec.
What Happens When You Run flutter run on 3.44+ 🏃
“The CLI does more than you’d expect. And it modifies files you might not expect it to touch.”
When you turn on Swift Package Manager and run the iOS app using the Flutter CLI, the CLI automatically updates your Xcode project to use Swift Package Manager. This makes your project download the Swift packages that your Flutter plugins depend on.
Specifically, the automatic iOS migration modifies the ios/Runner.xcodeproj/project.pbxproj and ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme files. If the automatic migration fails for any reason, there's a manual path documented in Flutter's official migration guide.
For existing projects on 3.44, SPM is on by default. For projects that hit build issues, there’s a temporary escape hatch:
flutter config --no-enable-swift-package-manager
This rolls back to the CocoaPods path. The operative word is temporary — this fallback exists to unblock you, not to be a permanent home. Real-world evidence of this: teams upgrading to Flutter 3.44.0 are already documenting that disabling SPM integration is sometimes necessary to unblock iOS builds during the migration period.
What This Means If You Maintain a Flutter Plugin 🔧
“This is the section I most want plugin maintainers to actually read. Not because the migration is hard — it largely isn’t — but because the consequence of not doing it is real and coming fast.”
Here’s the concrete reality for plugin maintainers right now:
pub.dev is penalizing unmigrated plugins. To encourage adoption, packages without Swift Package Manager support now receive lower pub.dev scores until they migrate. That score affects discoverability. Developers searching for a package will see your plugin ranked lower than an equivalent one that has migrated. For plugins competing in crowded categories — camera, location, notifications — that visibility difference is meaningful.
Flutter’s tooling is already sending you automated issues. The Flutter team has been automatically opening GitHub issues on popular plugins prompting maintainers to add Swift Package Manager support, and these messages are now going out systematically. If you maintain a plugin with any meaningful usage and haven’t gotten one of these yet, it’s likely coming.
The migration is largely mechanical. The actual steps — restructuring the Sources/ directory, writing a Package.swift, updating the .podspec to reference the new file paths, updating CI to test both paths — are documented thoroughly in Flutter's official migration guide. The workmanager plugin's migration is a good real-world example of what the PR actually looks like: it moved source files to Sources/workmanager_apple/, added a Package.swift, updated the podspec to reference the new locations, and added CI matrix testing for both CocoaPods and SPM simultaneously.
The December deadline isn’t about SPM. It’s about CocoaPods. If your plugin relies on other CocoaPods-only dependencies (things that haven’t migrated their native library to SPM themselves), you have a harder problem than just updating your file structure — you need those upstream native libraries to be available as Swift packages. That’s the case worth auditing now rather than in late November.
Breaking changes from Objective-C. Flutter will no longer generate Objective-C code going forward — it will be up to developers to handle Objective-C integration themselves, as with any native Darwin project. Plugins written in Objective-C still work, but new Flutter plugins will default to Swift, and the migration tooling is built around Swift. If your plugin is ObjC-heavy, the SPM migration is a good time to evaluate whether a Swift rewrite makes sense.
The Ecosystem Status Right Now 📊
“92 of the top 100 iOS plugins have migrated. The remaining 8 matter a lot depending on which ones you depend on.”
From my Flutter 3.47 deep-dive, I noted that 92 of the top 100 iOS plugins have already migrated to Swift Package Manager. That’s genuinely impressive ecosystem momentum for a migration that’s been underway for less than a year since becoming the default.
The 8 that haven’t migrated yet are the interesting ones. For any project that depends on one of them, the CocoaPods fallback keeps things working today. Come December 2nd, when the CocoaPods registry freezes, those plugins can’t publish new versions to trunk — which means if your project depends on one of them, you’re either stuck on whatever version was last published, or you wait for the maintainer to migrate. Or you fork and maintain your own SPM-capable version, which is always an option under pub.dev’s MIT-licensed ecosystem.
For App Developers: What You Actually Need to Do 🛠️
“Much less than you’d think. The CLI handles most of it.”
If you’re on Flutter 3.44 or later and you haven’t done anything:
- SPM is already on by default
- The CLI has already migrated your project files automatically when you last ran flutter run
- Plugins that support SPM are resolving through SPM
- Plugins that don’t yet have SPM support are falling back to CocoaPods transparently
The things worth actively checking:
# Verify your Flutter version
flutter --version
# Check if SPM migration happened (look for Package.swift references)
cat ios/Runner.xcodeproj/project.pbxproj | grep -i "swift"
# If you need to temporarily fall back
flutter config --no-enable-swift-package-manager
If a build breaks after upgrading to 3.44+, the most common cause is a plugin that has SPM support but hasn’t correctly declared its dependencies in Package.swift — usually surfacing as a missing framework error in Xcode. The fix is almost always either disabling SPM temporarily or waiting for an updated plugin version.
Where I Land On This 💭
CocoaPods served the iOS and Flutter ecosystems for a long time, and the migration away from it is happening in a measured, reasonably well-managed way. The tooling does the heavy lifting for app developers. The ask for plugin maintainers is real but not enormous — it’s a file structure change, a new manifest file, and updated CI. The December deadline is firm, but two months is enough time for most plugins.
The part I genuinely appreciate about how Flutter handled this: they didn’t just flip the default and leave maintainers to discover the breaking change in their error logs. They built automated issue-opening tooling, wrote thorough migration guides, lowered pub.dev scores to create genuine incentive, and kept the CocoaPods fallback running long enough for the ecosystem to catch up without everything breaking at once.
That’s a difficult migration to orchestrate at ecosystem scale. Worth acknowledging it’s being done reasonably well.
Tags: Flutter, Swift Package Manager, iOS Development, CocoaPods, Mobile Development, Dart, Plugin Development
Before you go
- Please take a moment to like the post and follow the writer!
- Did you know that over 400,000 developers share what they’re building, learning, and discovering across our platforms every month? Learn how you can contribute here.
Flutter’s Swift Package Manager Migration Is Here — And If You Maintain a Plugin, You Need to Read… was originally published in Stackademic on Medium, where people are continuing the conversation by highlighting and responding to this story.
