In this article

Move a Flutter iOS project to Swift Package Manager by auditing plugin support first. Do not remove CocoaPods while a dependency still needs the fallback. A package-manager change is complete when your required build configurations and plugin features work, not when one generated file appears.

Flutter’s app-developer SwiftPM guide says support is enabled by default from Flutter 3.44 and that dependencies without SwiftPM support can fall back to CocoaPods. Its removal instructions require checking all plugins before removing CocoaPods. Follow the guide matching your installed version.

Create a plugin readiness ledger#

For every plugin with an iOS native component, record:

  • The resolved version, not only the constraint in pubspec.yaml.
  • Its documented SwiftPM support and native dependency.
  • Any custom Podfile logic your application adds.
  • Features used by the app and a way to verify each one.
  • The owner of an unresolved migration requirement.

A hypothetical project may use camera, authentication and notification plugins. A successful launch exercises none of their full behavior. The ledger should assign a practical check to each used feature rather than mark every row ready because the home screen opens.

Establish the baseline before migrating#

Keep a reviewed branch with a working build and dependency files. Record Flutter, Xcode and configuration. Run the same checks you intend to repeat after migration so differences have a reference point.

Inspect any manually maintained native integration. A custom build phase, extra native target or non-plugin dependency may require attention beyond the default Flutter project.

Do not combine this transition with arbitrary package upgrades. Upgrade a plugin when its documented compatibility requires it, and record why.

Follow the version-scoped integration path#

Use Flutter’s current guide for automatic migration, explicit enabling, custom targets and fallback. Inspect the resulting project changes rather than assuming generated changes are always appropriate for a customized app.

When the app uses flavors, check each shared scheme and configuration. A development scheme working locally does not establish that the release archive uses the same dependency integration.

If a package needs a higher deployment target, treat that as a compatibility decision. Identify which package imposes it and what devices the change affects before modifying every target.

Keep mixed integration deliberate#

While unsupported plugins require CocoaPods, document the mixed state and keep its required CI tools. Do not interpret a future registry policy as proof that every existing dependency stops building immediately. Any claimed registry date should be checked against its upstream announcement before planning around it.

Once the ledger shows every required dependency and custom addition is ready, follow the official cleanup steps in a reviewable commit. Removing old integration files before this point can create a failure that looks unrelated to the actual unsupported plugin.

Verify both installation and behavior#

Perform a clean dependency resolution, build the intended release configuration and exercise each ledger feature on a suitable test device. Also test your actual CI archive path. Check that a cached local installation is not hiding missing setup.

If a step fails, capture its exact stage, plugin version and project change. Use the documented fallback for your version while investigating; do not make unsupported project edits just to silence a message.

The result should be a small migration record: what changed, which features were verified and which dependencies remain mixed. These are documentation-based checks, not claims of hands-on testing of your app. For release-stage context, see Meet CascadeCI.