effidevFlutter · Edge de Cloudflare · Optimización de costes en la nube
Español

Flutter Swift Package Manager: Guía Completa de Migración

Diagrama de migración de Flutter Swift Package Manager desde CocoaPods

El fin de CocoaPods ha comenzado

El 2 de diciembre de 2026, el registro trunk de CocoaPods pasará a ser solo lectura permanente. Esto significa que ya no se podrán publicar nuevos pods ni actualizar los existentes. Es el anuncio del fin práctico de la herramienta de gestión de dependencias de la que los desarrolladores de Flutter iOS han dependido durante casi 10 años.

El equipo de Flutter comenzó a preparar el soporte para Swift Package Manager (SwiftPM) desde 2024. Y en Flutter 3.44, SwiftPM se ha convertido en el gestor de dependencias predeterminado para iOS/macOS. Al ejecutar flutter run, Flutter CLI actualiza automáticamente el proyecto Xcode basándose en SwiftPM.

Este artículo aborda ambas perspectivas:

  1. Desarrolladores de aplicaciones: Cómo migrar proyectos de Flutter existentes basados en CocoaPods a SwiftPM.
  2. Autores de plugins: Cómo añadir Package.swift para que los plugins de pub.dev admitan SwiftPM.

Si no realiza la migración ahora, las dependencias de iOS quedarán prácticamente congeladas después de diciembre de 2026.

CocoaPods vs Swift Package Manager: Diferencias clave

Elemento CocoaPods Swift Package Manager
Entidad gestora Proyecto de código abierto independiente Soporte oficial de Apple
Archivo de configuración Podfile Package.swift
Integración con Xcode Crea .xcworkspace Integración nativa con Xcode
Velocidad de compilación Lenta (preprocesamiento basado en Ruby) Rápida (nativa)
Caché de binarios Limitada Integrada (caché .build)
Estado posterior a 2026 Solo lectura (Finalizado) En desarrollo activo
Puntuación en pub.dev Inicio de penalización Preferencial

La mayor ventaja de SwiftPM es su integración nativa con Xcode. No requiere ejecutar pod install por separado y se puede compilar directamente con .xcodeproj en lugar de requerir un archivo .xcworkspace.

Desarrolladores de aplicaciones: Migración automática

Si utiliza Flutter 3.44 o superior, en la mayoría de los casos la migración se realiza automáticamente.

1. Verificar la versión de Flutter

flutter --version
# Verificar si es Flutter 3.44.0 o superior

flutter upgrade  # Actualizar si es necesario

2. Activar la migración automática

# Al ejecutarlo en un proyecto existente, Flutter CLI intenta automáticamente la migración a SwiftPM
flutter run

# O activarlo explícitamente
flutter config --enable-swift-package-manager
flutter run  # Aplica automáticamente la configuración de SwiftPM en ejecuciones posteriores

Contenido de la migración automática realizada por Flutter CLI:

  1. Añade la configuración de integración de SwiftPM en ios/Runner.xcodeproj/project.pbxproj.
  2. Añade la referencia FlutterGeneratedPluginSwiftPackage a la carpeta ios/.
  3. Añade Run Prepare Flutter Framework Script al esquema de compilación de Xcode.

3. Verificar el éxito de la migración

# Verificar en Xcode
open ios/Runner.xcworkspace

# O desde la terminal
cat ios/Runner.xcodeproj/project.pbxproj | grep "FlutterGeneratedPluginSwiftPackage"
# Si esta cadena está presente, la integración con SwiftPM se ha completado

En Xcode, los plugins aparecerán como paquetes SwiftPM en la pestaña Project Navigator → Package Dependencies.

4. Manejo de plugins no compatibles

Si hay plugins que aún no admiten SwiftPM, Flutter CLI mostrará una advertencia:

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.

En este caso, Flutter realiza un fallback automático: utiliza SwiftPM para los plugins compatibles y CocoaPods para los plugins no compatibles. El archivo Podfile se mantiene tal como está y solo se aplica a los plugins que requieren pod install.

Cómo manejar plugins no compatibles:

  1. Abrir un issue solicitando soporte para SwiftPM en el repositorio GitHub del plugin.
  2. Buscar plugins alternativos (verificar la compatibilidad con SwiftPM en pub.dev).
  3. Contribuir directamente con un PR que añada Package.swift.

5. Desactivación temporal (en caso de problemas)

Si SwiftPM causa errores de compilación, se puede desactivar temporalmente:

# pubspec.yaml — Desactivación temporal
flutter:
  config:
    enable-swift-package-manager: false

O bien:

flutter config --no-enable-swift-package-manager

⚠️ Esta opción es una medida de desvío temporal. Se prevé su eliminación alrededor de 2027, por lo que no debe dependerse de ella.

Desarrolladores de aplicaciones: Migración manual (Proyectos heredados)

Si la migración automática falla o se migra un proyecto antiguo, el proceso debe realizarse manualmente.

Lista de verificación previa a la migración

# Hacer copia de seguridad del estado actual
git checkout -b feat/spm-migration
git add -A && git commit -m "chore: before SPM migration"

# Verificar el soporte de SwiftPM para todos los plugins
cat pubspec.yaml | grep -A 50 "dependencies:"

Verifique el distintivo “Swift Package Manager support” en la página de pub.dev de cada plugin de Flutter.

Limpieza del archivo Podfile

# ios/Podfile (Se mantiene para fallback de plugins tras la migración)
platform :ios, '13.0'  # Verificar la versión mínima de iOS

# Tras la migración a SwiftPM, los plugins compatibles se excluyen automáticamente
# Especificar plugins utilizados únicamente con CocoaPods (si es necesario)
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

Ejecución de la migración

cd ios

# Limpiar la caché existente de CocoaPods
rm -rf Pods/ Podfile.lock

# Limpieza con Flutter
cd ..
flutter clean

# Reinstalación de dependencias (Uso mixto de SwiftPM + CocoaPods)
flutter pub get
cd ios && pod install  # Para plugins que aún lo requieren
cd ..

# Prueba de compilación
flutter build ios --no-codesign

Autores de plugins: Añadir Package.swift

Si distribuye un plugin de Flutter en pub.dev, debe añadir soporte para SwiftPM. El sistema de puntuación de pub.dev ha incluido la compatibilidad con SwiftPM entre sus criterios de evaluación, por lo que no admitirlo provocará una penalización en la puntuación.

Modificación de la estructura de directorios

Estructura original con CocoaPods:

ios/
  Classes/
    MyPlugin.swift
    MyPlugin.h (En caso de uso mixto con Obj-C)
  my_plugin.podspec

Estructura tras añadir soporte para SwiftPM:

ios/
  my_plugin/           # Raíz del paquete SwiftPM (Novedad)
    Package.swift      # Manifiesto de SwiftPM
    Sources/
      my_plugin/       # Nombre del target = Nombre del paquete
        MyPlugin.swift
  Classes/             # Mantenido para retrocompatibilidad con CocoaPods
    MyPlugin.swift
  my_plugin.podspec    # podspec original mantenido

SwiftPM requiere estrictamente que los archivos de código fuente estén ubicados dentro de la raíz del paquete. CocoaPods permitía rutas fuera de la raíz, pero SwiftPM solo permite rutas estrictamente internas al paquete.

Creación de Package.swift

Para plugins escritos exclusivamente en Swift:

// 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",
            // En caso de tener dependencias externas de Swift
            // dependencies: [
            //   .product(name: "SomeSDK", package: "some-sdk"),
            // ]
        )
    ]
)

Plugin con uso mixto de Swift y Objective-C:

// 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",
            // Ubicación de las cabeceras públicas de Obj-C
            publicHeadersPath: "include",
            // Los archivos Obj-C también se incluyen en el mismo target
            cSettings: [
                .headerSearchPath("include"),
            ]
        )
    ]
)

SwiftPM no permite combinar Swift y Objective-C dentro del mismo target. Si el plugin utiliza tanto Objective-C como Swift, se deben separar en targets independientes:

targets: [
    // Target exclusivo para Objective-C
    .target(
        name: "my_plugin_objc",
        path: "Sources/my_plugin_objc",
        publicHeadersPath: "include"
    ),
    // El target Swift depende del target Obj-C
    .target(
        name: "my_plugin",
        dependencies: ["my_plugin_objc"],
        path: "Sources/my_plugin"
    )
]

Reubicación de la estructura de archivos fuente

# Crear el directorio de fuentes para SwiftPM
mkdir -p ios/my_plugin/Sources/my_plugin

# Copiar el código fuente existente (se mantiene el original para CocoaPods)
cp ios/Classes/MyPlugin.swift ios/my_plugin/Sources/my_plugin/
cp ios/Classes/MyPlugin.m ios/my_plugin/Sources/my_plugin/  # En caso de incluir Obj-C

Añadir la dependencia de Flutter Framework

Al utilizar las API nativas de Flutter (como el protocolo FlutterPlugin o FlutterMethodChannel), se debe especificar el Framework de Flutter como dependencia:

// ios/my_plugin/Package.swift
let package = Package(
    name: "my_plugin",
    platforms: [.iOS(.v13)],
    products: [
        .library(name: "my-plugin", targets: ["my_plugin"])
    ],
    dependencies: [
        // Añadir la dependencia de Flutter Framework (¡Imprescindible!)
        .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"
        )
    ]
)

Nota: Para la URL oficial de Package.swift de Flutter, utilice la ruta proporcionada por el equipo de Flutter. Flutter CLI inyecta automáticamente la ruta empaquetada dentro del SDK de Flutter durante la ejecución.

Actualización de pubspec.yaml

# pubspec.yaml (Plugin)
name: my_plugin
version: 2.0.0

flutter:
  plugin:
    platforms:
      ios:
        # Configuración de CocoaPods (Retrocompatibilidad)
        podspec: ios/my_plugin.podspec
        # Configuración adicional de SwiftPM
        swiftPackage: ios/my_plugin

Verificación: Prueba con la aplicación de ejemplo

# Activar la migración a SwiftPM en la aplicación de ejemplo del plugin
cd example

flutter config --enable-swift-package-manager
flutter run -d iPhone  # Dispositivo real o simulador

# Verificar en Xcode
open ios/Runner.xcworkspace
# Si my_plugin aparece en Package Dependencies, la prueba ha sido exitosa

Actualización del pipeline de CI

# .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"

# Prueba paralela de compilación clásica con CocoaPods (Verificación de retrocompatibilidad)
- name: Flutter iOS Build (CocoaPods fallback)
  run: |
    flutter config --no-enable-swift-package-manager
    flutter build ios --no-codesign --simulator

Cronograma de migración y niveles de riesgo

Momento Evento Nivel de riesgo
Flutter 3.44 (Actual) SwiftPM predeterminado Bajo (con fallback)
2 de diciembre de 2026 CocoaPods trunk en solo lectura Alto
Primer semestre de 2027 (Estimado) Eliminación de la opción de opt-out en Flutter Muy alto

Acciones a realizar ahora:

Imprescindible completar antes de diciembre de 2026:

Solución de problemas: Errores frecuentes

Error 1: “Sources folder not found”

error: Source files for target 'my_plugin' should be located under 'Sources/my_plugin'

Causa: SwiftPM requiere que los archivos fuente se ubiquen en la ruta Sources/<NombreTarget>/ dentro de la raíz del paquete.
Solución: Mover los archivos fuente a ios/my_plugin/Sources/my_plugin/.

Error 2: “Cannot use Swift and Objective-C in the same target”

Causa: SwiftPM no permite combinar lenguajes dentro del mismo target.
Solución: Separar en un target exclusivo para Obj-C y otro target para Swift.

Error 3: Se sigue utilizando solo CocoaPods incluso tras ejecutar pod install

# Verificar si el modo SwiftPM está forzado
flutter config | grep swift-package-manager

# Si no está activado
flutter config --enable-swift-package-manager
flutter clean && flutter pub get

Error 4: “FlutterGeneratedPluginSwiftPackage not found”

# Limpieza de la caché de Xcode
rm -rf ~/Library/Developer/Xcode/DerivedData
cd ios && xcodebuild -resolvePackageDependencies

Error 5: Advertencias relacionadas con Bitcode

SwiftPM desactiva Bitcode por defecto. Puesto que Apple marcó Bitcode como obsoleto a partir de iOS 16, esta advertencia puede ignorarse.

Impacto en la puntuación de pub.dev

Desde 2025, pub.dev ha incluido la compatibilidad con SwiftPM en la evaluación de la puntuación de los plugins. Categorías de puntuación:

Nivel de soporte Impacto en la puntuación de pub.dev
Soporte para SwiftPM y CocoaPods Puntuación máxima
Soporte solo para CocoaPods Penalización (alrededor de -10 puntos)
Sin soporte (excepto plugins exclusivamente Dart) Visualización de advertencias adicionales

La puntuación de pub.dev, sobre un máximo de 100 puntos, afecta directamente a la posición en los resultados de búsqueda. El soporte para SwiftPM ya no es opcional, sino obligatorio.

Conclusión

El fin de CocoaPods representa uno de los cambios más trascendentales en el ecosistema de Flutter iOS. La transición a Swift Package Manager no es una mera sustitución de herramientas, sino el retorno al ecosistema oficial de Apple.

La buena noticia para los desarrolladores de aplicaciones es que, en la mayoría de los casos, la migración se realiza automáticamente con una sola ejecución de flutter run. Los problemas surgen principalmente al depender de plugins que aún no admiten SwiftPM.

Si es autor de plugins, debe añadir Package.swift de inmediato. A partir de diciembre de 2026, será imposible publicar nuevas versiones en CocoaPods.

Plan de acción:

  1. Ejecutar flutter config --enable-swift-package-manager.
  2. Probar la compilación con flutter run.
  3. Verificar la lista de plugins con advertencias y definir un plan de respuesta.
  4. (Autores de plugins) Añadir Package.swift y publicar en pub.dev.

Artículos relacionados: Consulta también la optimización para Android de aplicaciones Flutter en Tamaño de página de 16 KB en Flutter y optimización de Google Play.