Passer à la navigation principale

Comment utiliser les traits de package SPM dans Capacitor 8

Utilisez les traits de package SPM dans Capacitor 8 : activez les fonctionnalités de plugin facultatives avec packageTraits, définissez swiftToolsVersion 6.1 et ajoutez des traits à votre propre plugin.

Crédits de l'article

Martin Donadieu

Auteur

Valeria

Réviseur

Jordan

Éditeur

Comment utiliser les traits de package SPM dans Capacitor 8

To use SPM package traits in Capacitor 8, set experimental.ios.spm.swiftToolsVersion à "6.1" et listez les traits par plugin sous experimental.ios.spm.packageTraits sur votre Capacitor de configuration, puis exécutez bunx cap sync ios. Le CLI écrit ces traits dans le fichier généré CapApp-SPM/Package.swift, et SwiftPM construit le plugin avec les dépendances optionnelles correspondantes et les chemins code . Cela nécessite Capacitor CLI 8.3.0 ou ultérieur et ne s'applique qu'aux projets iOS utilisant Swift Package Manager.

Les traits de package ferment le dernier grand écart entre SPM et CocoaPods pour les plugins : les dépendances natives optionnelles qui étaient auparavant des sous-é spécifications de pod.

Qu'est-ce que les traits de package ?

Les traits de package proviennent de la proposition Swift Evolution. SE-0450, mise en œuvre dans Swift 6.1 (Xcode 16.3 et ultérieur). Un package déclare des traits nommés dans son Package.swiftLes consommateurs choisissent lesquels activer lorsqu'ils dépendent du package. Un trait peut :

  • faire une dépendance optionnelle (condition: .when(traits: [...]) sur une dépendance cible),
  • activer les chemins code , puisque chaque trait activé est disponible en tant que condition de compilation (#if TraitName),
  • toggle build settings such as defines or linker flags,
  • activez d'autres traits.

Un package peut également marquer des traits par défaut. Ils sont activés sauf si le consommateur passe une liste explicite.

Si vous connaissez les subspecs CocoaPods ou les fonctionnalités Cargo en Rust, c'est la même idée.

Pourquoi cela compte dans Capacitor

Capacitor génère l'application. Package.swift for you, so you can’t hand-edit dependency lines to pass traits. Before CLI 8.3, plugin authors with an optional native SDK had two bad choices on SPM: always link the SDK, increasing size and sometimes adding privacy or export compliance work, or publish a second plugin. Common cases:

  • encrypted vs SQLite non chiffré (SQLCipher)
  • Les SDK d'analyse avec et sans collecte de l'identifiant publicitaire.
  • an optional vendor SDK for one payment or login provider,
  • Outil de débogage.

Activer les traits dans votre application

1. Vérifiez les versions

bunx cap --version      # 8.3.0 or later
xcodebuild -version     # Xcode 26 (required by Capacitor 8 anyway)

Le projet doit utiliser SPM : ios/App/CapApp-SPM existe. Si vous utilisez CocoaPods, voir comment migrer votre Capacitor application vers SPM.

2. Trouvez les noms de traits du plugin

Ouvrez le fichier Package.swift in node_modules et recherchez le traits: array ou consultez son fichier README. Les noms de traits sont sensibles à la casse.

3. Configurez 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;

Le clé est le nom de package du plugin npm. La valeur est la liste des traits à activer.

4. Synchronisez et vérifiez le résultat

bunx cap sync ios

Les éléments générés ios/App/CapApp-SPM/Package.swift qui commence désormais par // swift-tools-version: 6.1 et la ligne de dépendance du plugin comporte les traits :

.package(name: "AcmeCapacitorDb", path: "../../../node_modules/@acme/capacitor-db", traits: [.defaults, "SQLCipher"])

Le CLI écrit .defaults (or defaults, .default, default en tout cas) comme SwiftPM .defaults value, and every other name as a quoted string.

Construire dans Xcode. Si Xcode affiche toujours le graphique ancien, utilisez Les règles que le __CAPGO_KEEP_0__ impose.

Règles que CLI impose

Le Capacitor CLI vérifie la configuration lors de la synchronisation :

  • Si tout plugin a une liste de traits non vide et swiftToolsVersion is missing, sync stops avec « Les traits de package nécessitent une version explicite de Swift tools de 6.1 ou supérieure. »
  • Si swiftToolsVersion est inférieur à 6.1, la synchronisation s'arrête et vous indique que la version est trop basse.
  • swiftToolsVersion doit ressembler à 6.1 ou 6.1.0.
  • Les plugins avec un tableau vide sont traités comme s'ils n'étaient pas listés.

Conserver ou supprimer les caractéristiques par défaut

Lister les traits remplace les valeurs par défaut. Comparez :

La valeur de configuration Le résultat
non listé les traits par défaut du plugin
['SQLCipher'] seulement SQLCipher, par défaut désactivé
['.defaults', 'SQLCipher'] par défaut plus SQLCipher

Lisez les documents du plugin avant de supprimer les valeurs par défaut. Un plugin peut mettre son backend standard derrière un trait par défaut.

Ajoutez des traits à votre propre plugin

Si vous gérez un plugin avec un SDK facultatif, voici un exemple complet Package.swift. Le nom du package doit correspondre au nom que Capacitor CLI dérive de votre nom de npm (@acme/capacitor-db devient AcmeCapacitorDb). Consultez migrer un plugin Capacitor vers SPM pour la règle.

// 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]
)

Vérifiez le repository du SDK pour son URL de package, son nom de produit et sa version avant de copier cela.

Points qui sont faciles à manquer :

  • Les outils version 6.x changent le mode de langue par défaut en Swift 6 pour vos cibles. Capacitor n'approuve officiellement pas Swift 6 encore, donc gardez swiftLanguageModes: [.v5] à moins que votre code soit prêt pour la concurrence stricte.
  • Augmentez votre version d'outil de plugin à 6.1, ce qui signifie que les consommateurs nécessitent Xcode 16.3+. Capacitor 8 applications nécessitent déjà Xcode 26, donc ce n'est pas une nouvelle contrainte.

Utilisez le trait dans code

Les traits activés sont des conditions de compilation dans les cibles de votre package.

#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
}

Renvoyez une erreur claire en nommant le trait lorsque la fonctionnalité est désactivée. Les développeurs d'applications ne verront pas d'échec silencieux et blâmeront le plugin.

Vous pouvez également définir votre propre drapeau avec swiftSettings: [.define("ACME_SQLCIPHER", .when(traits: ["SQLCipher"]))] si vous préférez un nom préfixé.

Concevez les traits pour qu'ils soient additives

SwiftPM unifie les traits à travers le graphique de dépendance. Si deux packages dépendent de votre plugin avec différents traits, l'union est activée. Donc :

  • Activer un trait devrait ajouter des capacités, pas supprimer API ou modifier les valeurs par défaut.
  • Avoid mutually exclusive traits. If you can’t, fail the build loudly:
#if TraitA && TraitB
#error("TraitA and TraitB cannot be enabled together")
#endif

Testez chaque combinaison

swift build sur ses propres builds pour Mac, et un plugin qui dépend de Capacitor ne construit que pour iOS, alors testez les traits à travers une application de test Capacitor construite pour un simulateur iOS. Pour chaque combinaison (pas d'entrée pour les traits par défaut, ['SQLCipher'], ['.defaults', 'SQLCipher'] et ainsi de suite), changez 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

Ajoutez chaque combinaison à la CI comme un job à part.

Prenez en charge les utilisateurs de CocoaPods

Les traits n'existent que dans SPM. Si votre plugin fournit également un podspec, offrez le même choix que les sous-espèces :

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

Définir le même nom de condition de compilation dans la sous-spec permet de partager un #if SQLCipher Le chemin code. Les applications CocoaPods sélectionnent ensuite la sous-espèce dans leur fichier Podfile. Le Capacitor CLI écrit une. pod ligne par plugin à l'intérieur capacitor_podsDocumentez la ligne supplémentaire de Podfile dans votre fichier README. Comment utiliser CocoaPods avec Capacitor 8 montre où les lignes de pod personnalisées s'insèrent.

Limites

  • Expérimental. Les options se trouvent sous experimental et peuvent être déplacées vers ios.spm.* Dans une future majeure. Attendez une renommage de config à un moment donné.
  • Swift 6 non officiellement pris en charge. Les documents de CLI avertissent que la mise en place swiftToolsVersion to 6.0 or higher may cause issues. Test the full app, especially plugins that ship binary xcframeworks.
  • iOS uniquement. L'Android n'a pas d'équivalent dans Capacitor. Les plugins gèrent les SDK Android optionnels avec des variables Gradle dans variables.gradle ou des artefacts séparés.
  • Les plugins doivent s'inscrire. La plupart des plugins n'ont pas encore défini de traits. Vérifiez avant de planifier un.

Troubleshooting

La synchronisation faille avec « Les traits de package nécessitent une version explicite des outils Swift de 6.1 ou supérieure ». Ajouter swiftToolsVersion: '6.1' à côté de packageTraits.

SwiftPM signale un trait inconnu. Les noms de traits sont sensibles à la casse et doivent exister dans le plugin. Package.swift pour la version installée.

La fonctionnalité manque toujours après avoir activé le trait. Réinitialisez les caches de packages dans Xcode, nettoyez le dossier de build et confirmez le générateur. CapApp-SPM/Package.swift a le traits: suffixe. L'édition de ce fichier à la main ne fonctionne pas, car CLI le reécrit à chaque synchronisation.

Les erreurs dans Swift code après avoir augmenté la version des outils. C'est le mode de langage Swift 6 dans un package que vous contrôlez. Ajoutez swiftLanguageModes: [.v5].

Les conflits de nom entre les plugins. Depuis CLI 8.4, experimental.ios.spm.packageOptions vous pouvez définir symlink ou moduleAliases Puisque __CAPGO_KEEP_0__ 8.4 vous permet de définir Capacitor iOS troubleshooting guide.

Pour une vue plus large de SPM, lisez SPM vs CocoaPods pour CapacitorSi vous souhaitez des builds cloud qui exécutent déjà la version actuelle d'Xcode pour les projets SPM, consultez Capgo Construction.

Actualisations instantanées pour les applications Capacitor

When a web-layer bug is live, ship the fix through Capgo instead of waiting days for app store approval. Users get the update in the background while native changes stay in the normal review path.

Les dernières de notre Blog

Capgo gives you the best insights you need to create a truly professional mobile app.