Swift Package Manager para autores de plugins
Cómo agregar compatibilidad con Swift Package Manager a los plugins de iOS y macOS
Para obtener información sobre cómo desactivar y activar SwiftPM, visita Swift Package Manager para desarrolladores de aplicaciones.
Cómo agregar soporte de Swift Package Manager a un plugin de Flutter existente
#Esta guía muestra cómo agregar soporte de Swift Package Manager a un plugin que ya soporta CocoaPods. Esto asegura que el plugin sea utilizable por todos los proyectos de Flutter.
Los plugins de Flutter deben soportar tanto Swift Package Manager como CocoaPods hasta nuevo aviso.
La adopción de Swift Package Manager será gradual. A partir de Flutter 3.44, los plugins que no soportan CocoaPods no son utilizables por proyectos que aún no se han migrado a Swift Package Manager. Los plugins que no soportan Swift Package Manager pueden causar problemas a los proyectos que se han migrado. Por favor, migra tus plugins lo antes posible.
Reemplaza plugin_name a lo largo de esta guía con el nombre de tu plugin.
El ejemplo a continuación utiliza ios, reemplaza ios con macos
o darwin, según corresponda.
Asegúrate de que estás utilizando Flutter 3.44 o posterior. Esto activa SwiftPM por defecto.
-
Comienza creando un directorio bajo los directorios
ios,macosy/odarwin. Nombra este nuevo directorio con el nombre del paquete de la plataforma.plugin_name/
ios/
- …
- plugin_name/
-
Dentro de este nuevo directorio, crea los siguientes archivos/directorios:
Package.swift(archivo)Sources(directorio)Sources/plugin_name(directorio)
Tu plugin debería verse así:
plugin_name/
ios/
- …
plugin_name/
- Package.swift
Sources/
- plugin_name/
-
Utiliza la siguiente plantilla en el archivo
Package.swift:Package.swiftswift// swift-tools-version: 5.9 // The swift-tools-version declares the minimum version of Swift required to build this package. import PackageDescription let package = Package( // TODO: Update your plugin name. name: "plugin_name", platforms: [ // TODO: Update the platforms your plugin supports. // If your plugin only supports iOS, remove `.macOS(...)`. // If your plugin only supports macOS, remove `.iOS(...)`. .iOS("13.0"), .macOS("10.15") ], products: [ // TODO: Update your library and target names. // If the plugin name contains "_", replace with "-" for the library name. .library(name: "plugin-name", targets: ["plugin_name"]) ], dependencies: [ .package(name: "FlutterFramework", path: "../FlutterFramework") ], targets: [ .target( // TODO: Update your target name. name: "plugin_name", dependencies: [ .product(name: "FlutterFramework", package: "FlutterFramework") ], resources: [ // TODO: If your plugin requires a privacy manifest // (e.g. if it uses any required reason APIs), update the PrivacyInfo.xcprivacy file // to describe your plugin's privacy impact, and then uncomment this line. // For more information, visit: // https://developer.apple.com/documentation/bundleresources/privacy_manifest_files // .process("PrivacyInfo.xcprivacy"), // TODO: If you have other resources that need to be bundled with your plugin, refer to // the following instructions to add them: // https://developer.apple.com/documentation/xcode/bundling-resources-with-a-swift-package ] ) ] ) -
Actualiza las plataformas soportadas en tu archivo
Package.swift.Package.swiftswiftplatforms: [ // TODO: Update the platforms your plugin supports. // If your plugin only supports iOS, remove `.macOS(...)`. // If your plugin only supports macOS, remove `.iOS(...)`. .iOS("13.0"), .macOS("10.15") ], -
Actualiza los nombres del paquete, biblioteca y target en tu archivo
Package.swift.Package.swiftswiftlet package = Package( // TODO: Update your plugin name. name: "plugin_name", platforms: [ .iOS("13.0"), .macOS("10.15") ], products: [ // TODO: Update your library and target names. // If the plugin name contains "_", replace with "-" for the library name .library(name: "plugin-name", targets: ["plugin_name"]) ], dependencies: [ .package(name: "FlutterFramework", path: "../FlutterFramework") ], targets: [ .target( // TODO: Update your target name. name: "plugin_name", dependencies: [ .product(name: "FlutterFramework", package: "FlutterFramework") ], resources: [ // TODO: If your plugin requires a privacy manifest // (e.g. if it uses any required reason APIs), update the PrivacyInfo.xcprivacy file // to describe your plugin's privacy impact, and then uncomment this line. // For more information, visit: // https://developer.apple.com/documentation/bundleresources/privacy_manifest_files // .process("PrivacyInfo.xcprivacy"), // TODO: If you have other resources that need to be bundled with your plugin, refer to // the following instructions to add them: // https://developer.apple.com/documentation/xcode/bundling-resources-with-a-swift-package ] ) ] ) -
Si tu plugin tiene un archivo
PrivacyInfo.xcprivacy, muévelo aios/plugin_name/Sources/plugin_name/PrivacyInfo.xcprivacyy desmarca el comentario del recurso en el archivoPackage.swift.Package.swiftswiftresources: [ // TODO: If your plugin requires a privacy manifest // (e.g. if it uses any required reason APIs), update the PrivacyInfo.xcprivacy file // to describe your plugin's privacy impact, and then uncomment this line. // For more information, visit: // https://developer.apple.com/documentation/bundleresources/privacy_manifest_files .process("PrivacyInfo.xcprivacy"), // TODO: If you have other resources that need to be bundled with your plugin, refer to // the following instructions to add them: // https://developer.apple.com/documentation/xcode/bundling-resources-with-a-swift-package ], -
Mueve cualquier archivo de recursos de
ios/Assetsaios/plugin_name/Sources/plugin_name(o un subdirectorio). Agrega los archivos de recursos a tu archivoPackage.swift, si corresponde. Para obtener más instrucciones, visita Bundling resources with a Swift package. -
Mueve todos los archivos de
ios/Classesaios/plugin_name/Sources/plugin_name. -
Agrega
FlutterFrameworkcomo una dependencia.Actualiza
Package.swiftpara incluirFlutterFramework:Package.swiftswiftdependencies: [ .package(name: "FlutterFramework", path: "../FlutterFramework") ], targets: [ .target( // TODO: Update your target name. name: "plugin_name", dependencies: [ .product(name: "FlutterFramework", package: "FlutterFramework") ], ) ] -
Los directorios
ios/Assets,ios/Resourcesyios/Classesahora deberían estar vacíos y se pueden eliminar. -
Si tu plugin utiliza Pigeon, actualiza tu archivo de entrada de Pigeon.
pigeons/messages.dartdartkotlinOptions: KotlinOptions(), javaOut: 'android/app/src/main/java/io/flutter/plugins/Messages.java', javaOptions: JavaOptions(), swiftOut: 'ios/Classes/messages.g.swift', swiftOut: 'ios/plugin_name/Sources/plugin_name/messages.g.swift', swiftOptions: SwiftOptions(), -
Actualiza tu archivo
Package.swiftcon las personalizaciones que puedas necesitar.En Xcode, abre el directorio
ios/plugin_name/.En Xcode, abre tu archivo
Package.swift. Verify Xcode doesn't produce any warnings or errors for this file.Si tu archivo
ios/plugin_name.podspectiene dependencias deCocoaPods, agrega las correspondientes dependencias de Swift Package Manager a tuPackage.swift.Si tu paquete debe vincularse explícitamente como
staticodynamic(no recomendado por Apple), actualiza el Product para definir el tipo:Package.swiftswiftproducts: [ .library(name: "plugin-name", type: .static, targets: ["plugin_name"]) ],Realiza cualquier otra personalización. Para obtener más información sobre cómo escribir un archivo
Package.swift, visitaPackageDescription.
-
Actualiza tu archivo
ios/plugin_name.podspecpara que apunte a las nuevas rutas.ios/plugin_name.podspecrubys.source_files = 'Classes/**/*.swift' s.resource_bundles = {'plugin_name_privacy' => ['Resources/PrivacyInfo.xcprivacy']} s.source_files = 'plugin_name/Sources/plugin_name/**/*.swift' s.resource_bundles = {'plugin_name_privacy' => ['plugin_name/Sources/plugin_name/PrivacyInfo.xcprivacy']} -
Actualiza la carga de recursos desde el bundle para usar
Bundle.module.swift#if SWIFT_PACKAGE let settingsURL = Bundle.module.url(forResource: "image", withExtension: "jpg") #else let settingsURL = Bundle(for: Self.self).url(forResource: "image", withExtension: "jpg") #endif -
Si tu archivo
.gitignoreno incluye los directorios.build/y.swiftpm/, querrás actualizar tu.gitignorepara incluir:.gitignore.build/ .swiftpm/Confirma los cambios de tu plugin en tu sistema de control de versiones.
-
Verifica que el plugin aún funcione con CocoaPods.
Desactivar Swift Package Manager.
shflutter config --no-enable-swift-package-managerNavega a la aplicación de ejemplo del plugin.
shcd path/to/plugin/example/Asegúrate de que la aplicación de ejemplo del plugin se compile y se ejecute.
shflutter runNavega al directorio de nivel superior del plugin.
shcd path/to/plugin/Ejecuta los lints de validación de CocoaPods.
shpod lib lint ios/plugin_name.podspec --configuration=Debug --skip-tests --use-modular-headers --use-librariesshpod lib lint ios/plugin_name.podspec --configuration=Debug --skip-tests --use-modular-headers
-
Verifica que el plugin funcione con Swift Package Manager.
Activar Swift Package Manager.
shflutter config --enable-swift-package-managerNavega a la aplicación de ejemplo del plugin.
shcd path/to/plugin/example/Asegúrate de que la aplicación de ejemplo del plugin se compile y se ejecute.
shflutter runEn Xcode, abre la aplicación de ejemplo del plugin. Asegúrate de que Package Dependencies se muestre en el Project Navigator de la izquierda.
-
Verifica que las pruebas pasen.
Si tu plugin tiene pruebas unitarias nativas (XCTest), asegúrate de también actualizar las pruebas unitarias en la aplicación de ejemplo del plugin.
Sigue las instrucciones para probar plugins (testing plugins).
Reemplaza plugin_name a lo largo de esta guía con el nombre de tu plugin.
El ejemplo a continuación utiliza ios, reemplaza ios con macos
o darwin, según corresponda.
Asegúrate de que estás ejecutando Flutter 3.44 o posterior. Esto activa SwiftPM por defecto.
-
Comienza creando un directorio bajo los directorios
ios,macosy/odarwin. Nombra este nuevo directorio con el nombre del paquete de la plataforma.plugin_name/
ios/
- …
- plugin_name/
-
Dentro de este nuevo directorio, crea los siguientes archivos/directorios:
Package.swift(archivo)Sources(directorio)Sources/plugin_name(directorio)Sources/plugin_name/include(directorio)Sources/plugin_name/include/plugin_name(directorio)Sources/plugin_name/include/plugin_name/.gitkeep(file)- Este archivo asegura que el directorio se confirme.
Puedes eliminar el archivo
.gitkeepsi se agregan otros archivos al directorio.
- Este archivo asegura que el directorio se confirme.
Puedes eliminar el archivo
Tu plugin debería verse así:
plugin_name/
ios/
- …
plugin_name/
- Package.swift
Sources/plugin_name/include/plugin_name/
- .gitkeep/
-
Utiliza la siguiente plantilla en el archivo
Package.swift:Package.swiftswift// swift-tools-version: 5.9 // The swift-tools-version declares the minimum version of Swift required to build this package. import PackageDescription let package = Package( // TODO: Update your plugin name. name: "plugin_name", platforms: [ // TODO: Update the platforms your plugin supports. // If your plugin only supports iOS, remove `.macOS(...)`. // If your plugin only supports macOS, remove `.iOS(...)`. .iOS("13.0"), .macOS("10.15") ], products: [ // TODO: Update your library and target names. // If the plugin name contains "_", replace with "-" for the library name .library(name: "plugin-name", targets: ["plugin_name"]) ], dependencies: [ .package(name: "FlutterFramework", path: "../FlutterFramework") ], targets: [ .target( // TODO: Update your target name. name: "plugin_name", dependencies: [ .product(name: "FlutterFramework", package: "FlutterFramework") ], resources: [ // TODO: If your plugin requires a privacy manifest // (in other words, if it uses any required reason APIs), // update the PrivacyInfo.xcprivacy file // to describe your plugin's privacy impact, and then uncomment this line. // For more information, visit: // https://developer.apple.com/documentation/bundleresources/privacy_manifest_files // .process("PrivacyInfo.xcprivacy"), // TODO: If you have other resources that need to be bundled with your plugin, refer to // the following instructions to add them: // https://developer.apple.com/documentation/xcode/bundling-resources-with-a-swift-package ], cSettings: [ // TODO: Update your plugin name. .headerSearchPath("include/plugin_name") ] ) ] ) -
Actualiza las plataformas soportadas en tu archivo
Package.swift.Package.swiftswiftplatforms: [ // TODO: Update the platforms your plugin supports. // If your plugin only supports iOS, remove `.macOS(...)`. // If your plugin only supports macOS, remove `.iOS(...)`. .iOS("13.0"), .macOS("10.15") ], -
Actualiza los nombres del paquete, biblioteca y target en tu archivo
Package.swift.Package.swiftswiftlet package = Package( // TODO: Update your plugin name. name: "plugin_name", platforms: [ .iOS("13.0"), .macOS("10.15") ], products: [ // TODO: Update your library and target names. // If the plugin name contains "_", replace with "-" for the library name .library(name: "plugin-name", targets: ["plugin_name"]) ], dependencies: [ .package(name: "FlutterFramework", path: "../FlutterFramework") ], targets: [ .target( // TODO: Update your target name. name: "plugin_name", dependencies: [ .product(name: "FlutterFramework", package: "FlutterFramework") ], resources: [ // TODO: If your plugin requires a privacy manifest // (for example, if it uses any required reason APIs), // update the PrivacyInfo.xcprivacy file // to describe your plugin's privacy impact, and then uncomment this line. // For more information, visit: // https://developer.apple.com/documentation/bundleresources/privacy_manifest_files // .process("PrivacyInfo.xcprivacy"), // TODO: If you have other resources that need to be bundled with your plugin, refer to // the following instructions to add them: // https://developer.apple.com/documentation/xcode/bundling-resources-with-a-swift-package ], cSettings: [ // TODO: Update your plugin name. .headerSearchPath("include/plugin_name") ] ) ] ) -
Si tu plugin tiene un archivo
PrivacyInfo.xcprivacy, muévelo aios/plugin_name/Sources/plugin_name/PrivacyInfo.xcprivacyy desmarca el comentario del recurso en el archivoPackage.swift.Package.swiftswiftresources: [ // TODO: If your plugin requires a privacy manifest // (for example, if it uses any required reason APIs), // update the PrivacyInfo.xcprivacy file // to describe your plugin's privacy impact, and then uncomment this line. // For more information, visit: // https://developer.apple.com/documentation/bundleresources/privacy_manifest_files .process("PrivacyInfo.xcprivacy"), // TODO: If you have other resources that need to be bundled with your plugin, refer to // the following instructions to add them: // https://developer.apple.com/documentation/xcode/bundling-resources-with-a-swift-package ], -
Mueve cualquier archivo de recursos de
ios/Assetsaios/plugin_name/Sources/plugin_name(or a subdirectory). Agrega los archivos de recursos a tu archivoPackage.swift, si corresponde. Para obtener más instrucciones, visita https://developer.apple.com/documentation/xcode/bundling-resources-with-a-swift-package. -
Mueve cualquier cabecera pública de
ios/Classesaios/plugin_name/Sources/plugin_name/include/plugin_name.Si no estás seguro de qué cabeceras son públicas, comprueba el atributo
public_header_filesde tu archivopodspec. Si este atributo no está especificado, todas tus cabeceras eran públicas. Deberías considerar si deseas que todas tus cabeceras sean públicas.La clase
pluginClassdefinida en tu archivopubspec.yamldebe ser pública y estar dentro de este directorio.
-
Manejo de
modulemap.Omite este paso si tu plugin no tiene un
modulemap.Si estás usando un
modulemappara CocoaPods para crear un submódulo de prueba, considera eliminarlo para Swift Package Manager. Ten en cuenta que esto hace que todas las cabeceras públicas estén disponibles a través del módulo.Para eliminar el
modulemappara Swift Package Manager pero mantenerlo para CocoaPods, excluye elmodulemapy la cabecera umbrella en el archivoPackage.swiftdel plugin.El ejemplo a continuación asume que el
modulemapy la cabecera umbrella se encuentran en el directorioios/plugin_name/Sources/plugin_name/include.Package.swiftswift.target( name: "plugin_name", dependencies: [], exclude: ["include/cocoapods_plugin_name.modulemap", "include/plugin_name-umbrella.h"],Si deseas mantener tus pruebas unitarias compatibles tanto con CocoaPods como con Swift Package Manager, puedes intentar lo siguiente:
Tests/TestFile.mobjc@import plugin_name; @import plugin_name.Test; #if __has_include(<plugin_name/plugin_name-umbrella.h>) @import plugin_name.Test; #endifSi deseas utilizar un
modulemappersonalizado con tu paquete Swift, consulta la documentación de Swift Package Manager. -
Mueve todos los archivos restantes de
ios/Classesaios/plugin_name/Sources/plugin_name. -
Los directorios
ios/Assets,ios/Resourcesyios/Classesahora deberían estar vacíos y se pueden eliminar. -
Agrega
FlutterFrameworkcomo una dependencia.Actualiza
Package.swiftpara incluirFlutterFramework:Package.swiftswiftdependencies: [ .package(name: "FlutterFramework", path: "../FlutterFramework") ], targets: [ .target( // TODO: Update your target name. name: "plugin_name", dependencies: [ .product(name: "FlutterFramework", package: "FlutterFramework") ] ) ] -
Si tus archivos de cabecera ya no están en el mismo directorio que tus archivos de implementación, debes actualizar tus declaraciones de importación.
Por ejemplo, imagina la siguiente migración:
Antes:
ios/Classes/ ├── PublicHeaderFile.h └── ImplementationFile.mDespués:
ios/plugin_name/Sources/plugin_name/ └── include/plugin_name/ └── PublicHeaderFile.h └── ImplementationFile.m
En este ejemplo, se deben actualizar las declaraciones de importación en
ImplementationFile.m:Sources/plugin_name/ImplementationFile.mobjc#import "PublicHeaderFile.h" #import "./include/plugin_name/PublicHeaderFile.h" -
Si tu plugin utiliza Pigeon, actualiza tu archivo de entrada de Pigeon.
pigeons/messages.dartdartjavaOptions: JavaOptions(), objcHeaderOut: 'ios/Classes/messages.g.h', objcSourceOut: 'ios/Classes/messages.g.m', objcHeaderOut: 'ios/plugin_name/Sources/plugin_name/messages.g.h', objcSourceOut: 'ios/plugin_name/Sources/plugin_name/messages.g.m', copyrightHeader: 'pigeons/copyright.txt',Si tu archivo
objcHeaderOutya no está dentro del mismo directorio queobjcSourceOut, puedes cambiar el#importusandoObjcOptions.headerIncludePath:pigeons/messages.dartdartjavaOptions: JavaOptions(), objcHeaderOut: 'ios/Classes/messages.g.h', objcSourceOut: 'ios/Classes/messages.g.m', objcHeaderOut: 'ios/plugin_name/Sources/plugin_name/include/plugin_name/messages.g.h', objcSourceOut: 'ios/plugin_name/Sources/plugin_name/messages.g.m', objcOptions: ObjcOptions( headerIncludePath: './include/plugin_name/messages.g.h', ), copyrightHeader: 'pigeons/copyright.txt',Ejecuta Pigeon para volver a generar su código con la última configuración.
-
Actualiza tu archivo
Package.swiftcon las personalizaciones que puedas necesitar.En Xcode, abre el directorio
ios/plugin_name/.En Xcode, abre tu archivo
Package.swift. Verifica que Xcode no produzca advertencias o errores para este archivo.Si tu archivo
ios/plugin_name.podspectiene dependencias deCocoaPods, agrega las correspondientes dependencias de Swift Package Manager a tuPackage.swift.Si tu paquete debe vincularse explícitamente como
staticodynamic(no recomendado por Apple), actualiza el Product para definir el tipo:Package.swiftswiftproducts: [ .library(name: "plugin-name", type: .static, targets: ["plugin_name"]) ],Realiza cualquier otra personalización. Para obtener más información sobre cómo escribir un archivo
Package.swift, visita https://developer.apple.com/documentation/packagedescription.
-
Actualiza tu archivo
ios/plugin_name.podspecpara que apunte a las nuevas rutas.ios/plugin_name.podspecrubys.source_files = 'Classes/**/*.{h,m}' s.public_header_files = 'Classes/**/*.h' s.module_map = 'Classes/cocoapods_plugin_name.modulemap' s.resource_bundles = {'plugin_name_privacy' => ['Resources/PrivacyInfo.xcprivacy']} s.source_files = 'plugin_name/Sources/plugin_name/**/*.{h,m}' s.public_header_files = 'plugin_name/Sources/plugin_name/include/**/*.h' s.module_map = 'plugin_name/Sources/plugin_name/include/cocoapods_plugin_name.modulemap' s.resource_bundles = {'plugin_name_privacy' => ['plugin_name/Sources/plugin_name/PrivacyInfo.xcprivacy']} -
Actualiza la carga de recursos desde el bundle para usar
SWIFTPM_MODULE_BUNDLE:objc#if SWIFT_PACKAGE NSBundle *bundle = SWIFTPM_MODULE_BUNDLE; #else NSBundle *bundle = [NSBundle bundleForClass:[self class]]; #endif NSURL *imageURL = [bundle URLForResource:@"image" withExtension:@"jpg"]; -
Si tu directorio
ios/plugin_name/Sources/plugin_name/includesolo contiene un archivo.gitkeep, querrás actualizar tu.gitignorepara incluir lo siguiente:.gitignore!.gitkeepEjecuta
flutter pub publish --dry-runpara asegurar que el directorioincludeesté publicado. Confirma los cambios de tu plugin en tu sistema de control de versiones.
-
Verifica que el plugin aún funcione con CocoaPods.
Desactivar Swift Package Manager:
shflutter config --no-enable-swift-package-managerNavega a la aplicación de ejemplo del plugin.
shcd path/to/plugin/example/Asegúrate de que la aplicación de ejemplo del plugin se compile y se ejecute.
shflutter runNavega al directorio de nivel superior del plugin.
shcd path/to/plugin/Ejecuta los lints de validación de CocoaPods:
shpod lib lint ios/plugin_name.podspec --configuration=Debug --skip-tests --use-modular-headers --use-librariesshpod lib lint ios/plugin_name.podspec --configuration=Debug --skip-tests --use-modular-headers
-
Verifica que el plugin funcione con Swift Package Manager.
Activar Swift Package Manager:
shflutter config --enable-swift-package-managerNavega a la aplicación de ejemplo del plugin.
shcd path/to/plugin/example/Asegúrate de que la aplicación de ejemplo del plugin se compile y se ejecute.
shflutter runEn Xcode, abre la aplicación de ejemplo del plugin. Asegúrate de que Package Dependencies se muestre en el Project Navigator de la izquierda.
-
Verifica que las pruebas pasen.
Si tu plugin tiene pruebas unitarias nativas (XCTest), asegúrate de también actualizar las pruebas unitarias en la aplicación de ejemplo del plugin.
Sigue las instrucciones para probar plugins (testing plugins).
(Opcional, pero recomendado) Agregar el plugin como un paquete local en la aplicación de ejemplo
#Si tu plugin incluye un ejemplo, se recomienda agregar el plugin como un paquete local en la aplicación de ejemplo. Esto no es obligatorio, pero proporciona un mejor soporte de Xcode al editar el código fuente del plugin en la aplicación de ejemplo. Visita el issue #179032.
Agregar el plugin como paquete local
#En una terminal navega a
my_plugin.-
En Xcode, ejecuta el siguiente comando para abrir el workspace de la aplicación de ejemplo, (reemplaza
iosconmacossegún corresponda):
open example/ios/Runner.xcworkspace
-
Haz clic derecho en Flutter > Add Files to “Runner”.

-
Selecciona
my_plugin/ios/my_plugin(omacosodarwin, según corresponda). -
Asegúrate de que “Reference files in place” esté seleccionado (debería ser la opción predeterminada) y haz clic en Finish.

Esto agrega el plugin como un paquete local, pero está referenciado por una ruta absoluta, lo cual no es deseable para la distribución. Para cambiarlo a una ruta relativa, utiliza las siguientes instrucciones.
Cambiar a ruta relativa
#-
Copia la “Ruta completa” (Full Path) del plugin desde el File Inspector.

-
En la terminal:
open -a Xcode example/ios/Runner.xcodeproj/project.pbxproj -
Busca lo siguiente:
path = [COPIED FULL PATH]; sourceTree = "<absolute>"Por ejemplo:
path = /Users/username/path/to/my_plugin/ios/my_plugin; sourceTree = "<absolute>" -
Y reemplaza con la ruta relativa:
path = ../../ios/my_plugin; sourceTree = "<group>"(Ajusta
iosamacosodarwinsegún sea necesario).
Cómo actualizar las pruebas unitarias en la aplicación de ejemplo de un plugin
#Si tu plugin tiene XCTests nativos, es posible que debas actualizarlos para que funcionen con Swift Package Manager si se cumple una de las siguientes condiciones:
- Estás usando una dependencia de CocoaPods para la prueba.
- Tu plugin está configurado explícitamente como
type: .dynamicen su archivoPackage.swift.
Para actualizar tus pruebas unitarias:
En Xcode, abre tu
example/ios/Runner.xcworkspace.-
Si estabas usando una dependencia de CocoaPods para las pruebas, como
OCMock, querrás eliminarla de tu archivoPodfile.ios/Podfilerubytarget 'RunnerTests' do inherit! :search_paths pod 'OCMock', '3.5' endLuego en la terminal, ejecuta
pod installen el directorioplugin_name_ios/example/ios. -
Navega a Package Dependencies para el proyecto.

Las dependencias de paquetes del proyecto
-
Haz clic en el botón + y agrega cualquier dependencia exclusiva de pruebas buscándola en la barra de búsqueda superior derecha.

Buscar dependencias exclusivas de pruebas
-
Asegúrate de que la dependencia esté agregada al Target
RunnerTests.
Asegúrate de que la dependencia esté agregada al target
RunnerTests Haz clic en el botón Add Package.
-
Si has configurado explícitamente el tipo de biblioteca de tu plugin como
.dynamicen su archivoPackage.swift(no recomendado por Apple), también deberás agregarlo como una dependencia al targetRunnerTests.Asegúrate de que
RunnerTestsBuild Phases tenga una fase de compilación Link Binary With Libraries:
La fase de compilación
Link Binary With Librariesen el targetRunnerTestsSi la fase de compilación no existe ya, crea una. Haz clic en el botón add y luego haz clic en New Link Binary With Libraries Phase.

Agregar la fase de compilación
Link Binary With LibrariesNavega a Package Dependencies para el proyecto.
Haz clic en el botón add.
En el diálogo que se abre, haz clic en el botón Add Local....
Navega a
plugin_name/plugin_name_ios/ios/plugin_name_iosy haz clic en el botón Add Package.Asegúrate de que esté agregado al target
RunnerTestsy haz clic en el botón Add Package.
Asegúrate de que las pruebas pasen Product > Test.
A menos que se indique lo contrario, la documentación de este sitio refleja Flutter 3.44.0. Página actualizada por última vez el 2026-06-08. Ver código fuente oreportar un problema.