Flutter Swift Package Manager: CocoaPods Migration Guide

The End of CocoaPods Has Begun
On December 2, 2026, the CocoaPods trunk registry will transition to permanent read-only mode. This means you will no longer be able to publish new pods or update existing ones. It marks the effective end of the dependency management tool that Flutter iOS developers have relied on for nearly a decade.
The Flutter team has been preparing Swift Package Manager (SwiftPM) support since 2024. In Flutter 3.44, SwiftPM became the default dependency manager for iOS/macOS. Running flutter run automatically prompts the Flutter CLI to update your Xcode project to use SwiftPM.
This guide covers both perspectives:
- App Developers: How to migrate an existing CocoaPods-based Flutter project to SwiftPM
- Plugin Authors: How to add
Package.swiftso your pub.dev plugin supports SwiftPM
If you don’t migrate now, your iOS dependencies will effectively be frozen after December 2026.
CocoaPods vs Swift Package Manager: Key Differences
| Feature | CocoaPods | Swift Package Manager |
|---|---|---|
| Maintainer | Independent open-source project | Official Apple support |
| Config File | Podfile |
Package.swift |
| Xcode Integration | Generates .xcworkspace |
Native Xcode integration |
| Build Speed | Slow (Ruby-based preprocessing) | Fast (Native) |
| Binary Caching | Limited | Built-in (.build cache) |
| Post-2026 Status | Read-only (End of Life) | Actively developed |
| pub.dev Score | Penalty applied | Preferred |
The biggest advantage of SwiftPM is its native integration with Xcode. You no longer need a separate pod install, and you can build directly using .xcodeproj instead of a .xcworkspace file.
App Developers: Automatic Migration
If you are using Flutter 3.44 or higher, migration happens automatically in most cases.
1. Check Your Flutter Version
flutter --version
# Check if Flutter is 3.44.0 or higher
flutter upgrade # Upgrade if necessary
2. Trigger Automatic Migration
# Run in your existing project to let the Flutter CLI automatically attempt SwiftPM migration
flutter run
# Or explicitly enable it
flutter config --enable-swift-package-manager
flutter run # Subsequent runs will automatically apply SwiftPM settings
What the Flutter CLI automatically performs during migration:
- Adds SwiftPM integration configuration to
ios/Runner.xcodeproj/project.pbxproj - Adds a reference to
FlutterGeneratedPluginSwiftPackagein theios/directory - Adds
Run Prepare Flutter Framework Scriptto the Xcode build scheme
3. Verify Successful Migration
# Check in Xcode
open ios/Runner.xcworkspace
# Or in the terminal
cat ios/Runner.xcodeproj/project.pbxproj | grep "FlutterGeneratedPluginSwiftPackage"
# If this string is present, SwiftPM integration is complete
In Xcode under the Project Navigator → Package Dependencies tab, plugins will be displayed as SwiftPM packages.
4. Handling Unsupported Plugins
If any of your plugins do not support SwiftPM yet, the Flutter CLI displays a warning:
The following packages have native iOS code but are not compatible with Swift Package Manager:
- some_plugin (version: 1.2.3)
Flutter will use CocoaPods for these plugins only.
In this scenario, Flutter automatically falls back: supported plugins use SwiftPM, while unsupported plugins continue to use CocoaPods. Your Podfile remains intact and is applied only to plugins that still require pod install.
How to handle unsupported plugins:
- Open a SwiftPM support issue on the plugin’s GitHub repository
- Search for alternative plugins (check for SwiftPM support badges on pub.dev)
- Contribute directly by submitting a PR with
Package.swift
5. Temporarily Disabling (If Issues Arise)
If SwiftPM causes build errors, you can temporarily disable it:
# pubspec.yaml — Temporarily disable
flutter:
config:
enable-swift-package-manager: false
Or:
flutter config --no-enable-swift-package-manager
⚠️ This option is a temporary workaround. It is expected to be removed around 2027, so do not rely on it long term.
App Developers: Manual Migration (Legacy Projects)
If automatic migration fails or if you are migrating an older project, follow these manual steps.
Pre-Migration Checklist
# Backup current state
git checkout -b feat/spm-migration
git add -A && git commit -m "chore: before SPM migration"
# Check SwiftPM support for all plugins
cat pubspec.yaml | grep -A 50 "dependencies:"
Check for the “Swift Package Manager support” badge on each Flutter plugin’s pub.dev page.
Cleaning Up Podfile
# ios/Podfile (Retained for plugin fallbacks post-migration)
platform :ios, '13.0' # Verify minimum iOS version
# Supported plugins are automatically excluded after SwiftPM migration
# Explicitly specify CocoaPods-only plugins (if needed)
target 'Runner' do
use_frameworks!
use_modular_headers!
flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
target 'RunnerTests' do
inherit! :search_paths
end
end
Executing Migration
cd ios
# Clean existing CocoaPods cache
rm -rf Pods/ Podfile.lock
# Flutter Clean
cd ..
flutter clean
# Reinstall dependencies (Hybrid SwiftPM + CocoaPods)
flutter pub get
cd ios && pod install # Only for plugins that still require it
cd ..
# Build test
flutter build ios --no-codesign
Plugin Authors: Adding Package.swift
If you publish a Flutter plugin on pub.dev, you must add SwiftPM support. The pub.dev scoring system now includes SwiftPM support as an evaluation metric, meaning unsupported plugins will receive a score penalty.
Directory Structure Changes
Previous CocoaPods Structure:
ios/
Classes/
MyPlugin.swift
MyPlugin.h (if mixing Obj-C)
my_plugin.podspec
Structure After Adding SwiftPM Support:
ios/
my_plugin/ # SwiftPM package root (newly added)
Package.swift # SwiftPM manifest
Sources/
my_plugin/ # Target name = Package name
MyPlugin.swift
Classes/ # Retained for CocoaPods backward compatibility
MyPlugin.swift
my_plugin.podspec # Retained existing podspec
SwiftPM strictly requires source files to be located inside the package root. While CocoaPods allowed paths outside the root, SwiftPM strictly enforces package-internal paths.
Writing Package.swift
For pure Swift plugins:
// ios/my_plugin/Package.swift
// swift-tools-version: 5.9
import PackageDescription
let package = Package(
name: "my_plugin",
platforms: [
.iOS(.v13),
],
products: [
.library(
name: "my-plugin",
targets: ["my_plugin"]
)
],
dependencies: [],
targets: [
.target(
name: "my_plugin",
dependencies: [],
path: "Sources/my_plugin",
// If you have external Swift dependencies:
// dependencies: [
// .product(name: "SomeSDK", package: "some-sdk"),
// ]
)
]
)
For mixed Swift + Objective-C plugins:
// ios/my_plugin/Package.swift
// swift-tools-version: 5.9
import PackageDescription
let package = Package(
name: "my_plugin",
platforms: [
.iOS(.v13),
],
products: [
.library(name: "my-plugin", targets: ["my_plugin"])
],
targets: [
.target(
name: "my_plugin",
dependencies: [],
path: "Sources/my_plugin",
// Specify public header path for Obj-C
publicHeadersPath: "include",
// Obj-C files are included in the same target
cSettings: [
.headerSearchPath("include"),
]
)
]
)
SwiftPM cannot mix Swift and Objective-C within the same target. If your plugin uses both Objective-C and Swift, you must separate them into distinct targets:
targets: [
// Objective-C target only
.target(
name: "my_plugin_objc",
path: "Sources/my_plugin_objc",
publicHeadersPath: "include"
),
// Swift target depends on Obj-C target
.target(
name: "my_plugin",
dependencies: ["my_plugin_objc"],
path: "Sources/my_plugin"
)
]
Rearranging Source File Structure
# Create source directory for SwiftPM
mkdir -p ios/my_plugin/Sources/my_plugin
# Copy existing sources (retain originals for CocoaPods)
cp ios/Classes/MyPlugin.swift ios/my_plugin/Sources/my_plugin/
cp ios/Classes/MyPlugin.m ios/my_plugin/Sources/my_plugin/ # If Obj-C is used
Adding Flutter Framework Dependency
If you use Flutter native APIs (such as the FlutterPlugin protocol or FlutterMethodChannel), you must declare the Flutter Framework as a dependency:
// ios/my_plugin/Package.swift
let package = Package(
name: "my_plugin",
platforms: [.iOS(.v13)],
products: [
.library(name: "my-plugin", targets: ["my_plugin"])
],
dependencies: [
// Add Flutter Framework dependency (Required!)
.package(
url: "https://github.com/nicehash/flutter",
from: "1.0.0"
)
],
targets: [
.target(
name: "my_plugin",
dependencies: [
.product(name: "Flutter", package: "flutter")
],
path: "Sources/my_plugin"
)
]
)
Note: For the official Flutter
Package.swiftURL, use the path provided by the Flutter team. In practice, the Flutter CLI automatically injects the bundled framework path from the Flutter SDK when executed.
Updating pubspec.yaml
# pubspec.yaml (Plugin)
name: my_plugin
version: 2.0.0
flutter:
plugin:
platforms:
ios:
# CocoaPods configuration (backward compatibility)
podspec: ios/my_plugin.podspec
# SwiftPM configuration added
swiftPackage: ios/my_plugin
Verification: Testing with an Example App
# Enable SwiftPM migration in the plugin's example app
cd example
flutter config --enable-swift-package-manager
flutter run -d iPhone # Physical device or simulator
# Check in Xcode
open ios/Runner.xcworkspace
# If my_plugin appears under Package Dependencies, migration succeeded
Updating the CI Pipeline
# .github/workflows/test.yml
- name: Flutter iOS Build (SwiftPM)
run: |
flutter config --enable-swift-package-manager
flutter build ios --no-codesign --simulator
env:
FLUTTER_VERSION: "3.44.0"
# Parallel test for CocoaPods build (verify backward compatibility)
- name: Flutter iOS Build (CocoaPods fallback)
run: |
flutter config --no-enable-swift-package-manager
flutter build ios --no-codesign --simulator
Migration Timeline and Risk Matrix
| Timeline | Event | Risk Level |
|---|---|---|
| Flutter 3.44 (Current) | SwiftPM becomes default | Low (Fallback available) |
| December 2, 2026 | CocoaPods trunk read-only | High |
| Early 2027 (Expected) | Opt-out option removed from Flutter | Very High |
Action items for today:
- App Developers: Run
flutter config --enable-swift-package-managerand test your build - Plugin Authors: Add
Package.swiftand publish a new version to pub.dev
Must complete before December 2026:
- Verify SwiftPM support for all plugins used in your project
- Find alternatives for unsupported plugins or contribute via direct PRs
Troubleshooting: Common Errors
Error 1: “Sources folder not found”
error: Source files for target 'my_plugin' should be located under 'Sources/my_plugin'
Cause: SwiftPM requires source files to be located under Sources/<target_name>/ within the package root.
Solution: Move source files to ios/my_plugin/Sources/my_plugin/.
Error 2: “Cannot use Swift and Objective-C in the same target”
Cause: SwiftPM does not support mixing languages within a single target.
Solution: Separate into an Objective-C target and a Swift target.
Error 3: Still Using CocoaPods After pod install
# Check forced SwiftPM mode
flutter config | grep swift-package-manager
# If not enabled
flutter config --enable-swift-package-manager
flutter clean && flutter pub get
Error 4: “FlutterGeneratedPluginSwiftPackage not found”
# Clear Xcode cache
rm -rf ~/Library/Developer/Xcode/DerivedData
cd ios && xcodebuild -resolvePackageDependencies
Error 5: Bitcode Warnings
SwiftPM disables Bitcode by default. Since Apple deprecated Bitcode starting with iOS 16, you can safely ignore this warning.
Impact on pub.dev Scores
Starting in 2025, pub.dev included SwiftPM support as part of its plugin score calculations. Score categories:
| Support Level | pub.dev Score Impact |
|---|---|
| SwiftPM + CocoaPods both supported | Full points |
| CocoaPods only supported | Penalty (~10 points deducted) |
| Unsupported (Excludes Dart-only plugins) | Additional warning displayed |
Your pub.dev score out of 100 directly influences search ranking. SwiftPM support is no longer optional—it’s mandatory.
Conclusion
The sunset of CocoaPods marks one of the most significant shifts in the Flutter iOS ecosystem. Transitioning to Swift Package Manager is not just a tool swap; it’s a return to Apple’s official ecosystem.
The good news for app developers is that in most cases, a single flutter run handles the automatic migration. Issues generally arise only when you depend on plugins that do not yet support SwiftPM.
If you are a plugin author, you should add Package.swift right away. Publishing new versions to CocoaPods will become impossible after December 2026.
Action plan:
- Run
flutter config --enable-swift-package-manager - Test your build with
flutter run - Review warned plugins and establish remediation plans
- (Plugin authors) Add
Package.swiftand publish to pub.dev
Related post: Check out Android-side optimization for Flutter apps in Flutter 16KB Page Size and Google Play Optimization.