To use SPM package traits in Capacitor 8, set experimental.ios.spm.swiftToolsVersion to "6.1" y listar las características por plugin debajo experimental.ios.spm.packageTraits en su configuración de Capacitor, luego ejecute bunx cap sync ios. El CLI escribe esas características en el archivo generado CapApp-SPM/Package.swift, y SwiftPM construye el plugin con las dependencias opcionales y code que coinciden. Esto requiere Capacitor CLI 8.3.0 o posterior y solo se aplica a proyectos de iOS que utilizan el administrador de paquetes Swift.
Las características cierran la última gran brecha entre SPM y CocoaPods para plugins: dependencias nativas opcionales que antes eran subspecs de podspec. Esta guía cubre el lado de la aplicación, el lado del autor del plugin y los límites del soporte experimental actual.
¿Qué son las características de paquete?
Package traits come from Swift Evolution proposal SE-0450implementada en Swift 6.1 (Xcode 16.3 y posterior). Un paquete declara características nombradas en su Package.swiftLos consumidores eligen las que activar cuando dependen del paquete. Una característica puede:
- hacer una dependencia opcional (
condition: .when(traits: [...])en una dependencia de destino), - activar los code de rutas, ya que cada característica habilitada está disponible como una condición de compilación (
#if TraitName), - activar ajustes de compilación como definiciones o banderas del enlazador,
- habilitar otras características.
Un paquete también puede marcar características como predeterminadas. Están activas a menos que el consumidor pase una lista explícita.
Si conoces subspecs de CocoaPods o características de Cargo en Rust, es la misma idea.
¿Por qué importa en Capacitor
Capacitor genera las dependencias de la aplicación Package.swift para ti, por lo que no puedes editar manualmente las líneas de dependencia para pasar características. Antes de CLI 8.3, los autores de plugins con un SDK nativo opcional tenían dos malas opciones en SPM: siempre enlazar el SDK, aumentando el tamaño y a veces agregando trabajo de privacidad o cumplimiento de exportación, o publicar un segundo plugin. Casos comunes:
- versión cifrada vs. SQLite plano (SQLCipher),
- SDK de análisis con y sin recopilación del identificador de publicidad,
- un proveedor de pago o de inicio de sesión opcional SDK
- Herramientas de depuración solo para depurar.
Habilitar características en tu aplicación
1. Verifica las versiones
bunx cap --version # 8.3.0 or later
xcodebuild -version # Xcode 26 (required by Capacitor 8 anyway)
El proyecto debe utilizar SPM: ios/App/CapApp-SPM existe. Si estás en CocoaPods, vea cómo migrar tu aplicación Capacitor a SPM.
2. Encuentra los nombres de las características del plugin
Abre el archivo Package.swift in node_modules o revisa su README. Los nombres de las características son sensibles a mayúsculas y minúsculas. traits: array o revisa su README. Los nombres de las características son sensibles a la casilla.
3. Configura Capacitor
import type { CapacitorConfig } from '@capacitor/cli';
const config: CapacitorConfig = {
appId: 'com.example.app',
appName: 'Example',
webDir: 'dist',
experimental: {
ios: {
spm: {
swiftToolsVersion: '6.1',
packageTraits: {
'@acme/capacitor-db': ['.defaults', 'SQLCipher'],
},
},
},
},
};
export default config;
La clave es el nombre del paquete del plugin npm. El valor es la lista de características a habilitar.
4. Sincronice y verifique el resultado
bunx cap sync ios
The generado ios/App/CapApp-SPM/Package.swift ahora comienza con // swift-tools-version: 6.1 y la línea de dependencia del plugin lleva las características:
.package(name: "AcmeCapacitorDb", path: "../../../node_modules/@acme/capacitor-db", traits: [.defaults, "SQLCipher"])
El CLI escribe .defaults (or defaults, .default, default y cada otro nombre como una cadena citada. .defaults valor, y cada otro nombre como una cadena de texto entre comillas.
Construya en Xcode. Si Xcode sigue mostrando el gráfico antiguo, utilice Las reglas que __CAPGO_KEEP_0__ impone.
Reglas que CLI aplica
El Capacitor CLI valida la configuración durante la sincronización:
- Si cualquier plugin tiene una lista de características no vacía y
swiftToolsVersionfalta, se detiene con “Los rasgos del paquete requieren una versión explícita de herramientas de Swift de 6.1 o superior.” - Si
swiftToolsVersiones inferior a 6.1, se detiene y te dice que la versión es demasiado baja. swiftToolsVersiondebe tener el formato6.1o6.1.0.- Plugins con un array vacío se tratan como si no se hubieran incluido.
Mantener o eliminar características predeterminadas
Lista de características reemplaza los valores por defecto. Comparar:
| Mantener o eliminar rasgos predeterminados | Result |
|---|---|
| no se incluye | Resultado no incluido en la lista |
['SQLCipher'] |
Solo SQLCipher, desactivado por defecto |
['.defaults', 'SQLCipher'] |
por defecto más SQLCipher |
Lee los documentos del plugin antes de desactivar los valores por defecto. Un plugin puede poner su backend estándar detrás de un valor por defecto.
Agregar características a tu propio plugin
Si mantienes un plugin con un SDK opcional, aquí tienes un ejemplo completo Package.swiftEl nombre del paquete debe coincidir con el nombre que Capacitor CLI deriva de tu npm.@acme/capacitor-db se convierte en AcmeCapacitorDb). Consulta migrar un plugin Capacitor a SPM para la regla.
// swift-tools-version: 6.1
import PackageDescription
let package = Package(
name: "AcmeCapacitorDb",
platforms: [.iOS(.v15)],
products: [
.library(name: "AcmeCapacitorDb", targets: ["DbPlugin"])
],
traits: [
.trait(name: "SQLCipher", description: "Link SQLCipher and enable encrypted databases."),
.default(enabledTraits: [])
],
dependencies: [
.package(url: "https://github.com/ionic-team/capacitor-swift-pm.git", from: "8.0.0"),
.package(url: "https://github.com/sqlcipher/SQLCipher.swift.git", from: "4.10.0")
],
targets: [
.target(
name: "DbPlugin",
dependencies: [
.product(name: "Capacitor", package: "capacitor-swift-pm"),
.product(name: "Cordova", package: "capacitor-swift-pm"),
.product(
name: "SQLCipher",
package: "SQLCipher.swift",
condition: .when(traits: ["SQLCipher"])
)
],
path: "ios/Sources/DbPlugin"
)
],
swiftLanguageModes: [.v5]
)
Verifique el repositorio propio del SDK para su URL de paquete, nombre de producto y versión antes de copiar esto.
Aspectos que pueden pasar desapercibidos:
- Las herramientas de versión 6.x cambian el modo de idioma predeterminado a Swift 6 para tus objetivos. Capacitor no admite oficialmente Swift 6 todavía, así que mantén
swiftLanguageModes: [.v5]a menos que tu code esté listo para la concurrencia estricta. - Aumentar la versión de herramientas de tu plugin a 6.1 significa que los consumidores necesitan Xcode 16.3+. Capacitor ya requiere Xcode 26 para 8 aplicaciones, así que no es una nueva restricción.
Utiliza la característica en code
Las características habilitadas son condiciones de compilación en los objetivos de tu paquete:
#if SQLCipher
import SQLCipher
#endif
@objc func open(_ call: CAPPluginCall) {
let key = call.getString("encryptionKey")
#if SQLCipher
// open with key
#else
if key != nil {
call.unavailable("Encryption requires the SQLCipher trait. Enable it in experimental.ios.spm.packageTraits.")
return
}
#endif
// open without encryption
}
Devuelve un error claro nombrando la característica cuando una función está desactivada. Los desarrolladores de aplicaciones de lo contrario ven un fallo silencioso y culpan al plugin.
También puedes definir tu propia bandera con swiftSettings: [.define("ACME_SQLCIPHER", .when(traits: ["SQLCipher"]))] si prefieres un nombre prefijado.
Diseña las características para que sean aditivas
SwiftPM unifica características a lo largo de la gráfica de dependencias. Si dos paquetes dependen de tu plugin con diferentes características, se habilita la unión. Entonces:
- Habilitar una característica debe agregar capacidades, no eliminar API o cambiar los valores por defecto.
- Evita características mutuamente excluyentes. Si no puedes, falla el build con un mensaje claro:
#if TraitA && TraitB
#error("TraitA and TraitB cannot be enabled together")
#endif
Prueba cada combinación
swift build en sus propias compilaciones para el Mac, y un plugin que depende de Capacitor solo compila para iOS, así que prueba las características a través de una aplicación de prueba Capacitor construida para un simulador de iOS. Para cada combinación (sin entrada para las características por defecto, ['SQLCipher'], ['.defaults', 'SQLCipher'] y así sucesivamente), cambia packageTraits in the test app’s config, then sync and build:
bunx cap sync ios
xcodebuild build \
-project ios/App/App.xcodeproj \
-scheme App \
-destination 'generic/platform=iOS Simulator' \
CODE_SIGNING_ALLOWED=NO
Agrega cada combinación a CI como su propio trabajo.
Mantén a los usuarios de CocoaPods cubiertos
Las características solo existen en SPM. Si tu plugin también envía un archivo podspec, ofrece la misma elección que los subspecs:
s.default_subspec = 'Core'
s.subspec 'Core' do |core|
core.source_files = 'ios/Sources/DbPlugin/**/*.swift'
core.dependency 'Capacitor'
end
s.subspec 'SQLCipher' do |sc|
sc.dependency 'AcmeCapacitorDb/Core'
sc.dependency 'SQLCipher', '~> 4.10'
sc.pod_target_xcconfig = { 'SWIFT_ACTIVE_COMPILATION_CONDITIONS' => '$(inherited) SQLCipher' }
end
Establecer el mismo nombre de condición de compilación en el subspec te permite compartir un #if SQLCipher code camino. Las aplicaciones CocoaPods luego seleccionan el subspec en su archivo Podfile. El Capacitor CLI escribe uno pod línea por plugin dentro capacitor_podsEntonces, documente la línea adicional de Podfile en su README. Cómo usar CocoaPods con Capacitor 8 muestra dónde van las líneas de pods personalizadas.
Limitaciones
- Experimental. Las opciones se encuentran debajo
experimentaly pueden moverse aios.spm.*en una futura versión mayor. Espera un cambio de configuración en algún momento. - No se admite oficialmente Swift 6. Los documentos de CLI advierten que establecer
swiftToolsVersiona 6.0 o superior puede causar problemas. Pruebe la aplicación completa, especialmente los plugins que envían xcframeworks binarios. - Solo para iOS. Android no tiene equivalente en Capacitor. Los plugins manejan SDKs de Android opcionales mediante variables de Gradle en
variables.gradleo artefactos separados. - Los plugins deben optar por ello. La mayoría de los plugins no definen características aún. Verifique antes de planificar una.
Troubleshooting
La sincronización falla con “Los rasgos del paquete requieren una versión explícita de herramientas de Swift de 6.1 o superior”. Add swiftToolsVersion: '6.1' Agregar packageTraits.
SwiftPM informa de un carácter desconocido. Trait names are case-sensitive and must exist in the plugin’s Package.swift SwiftPM informa una característica desconocida.
La característica sigue faltando después de habilitar el rasgo. Reinicia las cachés de paquetes en Xcode, limpia el carpeta de compilación y confirma la generada CapApp-SPM/Package.swift tiene el traits: reemplazo. Editar ese archivo a mano no funciona, ya que el CLI lo reescribe cada vez que se sincroniza.
Errores en Swift code después de aumentar la versión de las herramientas. Es el modo de idioma Swift 6 en un paquete que controlas. Agrega swiftLanguageModes: [.v5].
Conflictos de nombres entre plugins. Desde CLI 8.4, experimental.ios.spm.packageOptions te permite establecer symlink o moduleAliases por plugin. Más sobre eso en el Capacitor iOS troubleshooting guide.
Para la visión más grande de SPM, lee SPM vs CocoaPods para CapacitorSi deseas construcciones en la nube que ya ejecutan la versión actual de Xcode para proyectos SPM, consulta Capgo Construcción.