Saltar al contenido principal

Cómo usar las características de paquetes SPM en Capacitor 8

Utilice características de paquetes SPM en Capacitor 8: habilite características de plugins opcionales con packageTraits, establezca swiftToolsVersion 6.1 y agregue características a su propio plugin.

Créditos del artículo

Martín Donadieu

Escritor

Valeria

Revisor

Jordan

Editor

Cómo utilizar características de paquetes SPM en Capacitor 8

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 swiftToolsVersion falta, se detiene con “Los rasgos del paquete requieren una versión explícita de herramientas de Swift de 6.1 o superior.”
  • Si swiftToolsVersion es inferior a 6.1, se detiene y te dice que la versión es demasiado baja.
  • swiftToolsVersion debe tener el formato 6.1 o 6.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 experimental y pueden moverse a ios.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 swiftToolsVersion a 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.gradle o 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.

Actualizaciones en vivo para las aplicaciones Capacitor

Cuando un error de capa web está vivo, envíe la corrección a través de Capgo en lugar de esperar días a la aprobación de la tienda de aplicaciones. Los usuarios obtienen la actualización en segundo plano mientras los cambios nativos siguen en el camino de revisión normal.

Últimas noticias de nuestro Blog

Capgo te brinda las mejores perspectivas que necesitas para crear una aplicación móvil verdaderamente profesional.