Swift Package Manager en 2026 : Création, Publication et Questions d'Entretien

Guide complet sur Swift Package Manager. Apprenez à créer des packages Swift, gérer les dépendances, publier des bibliothèques et préparer les entretiens iOS.

Swift Package Manager en 2026 : Création, Publication et Questions d'Entretien

Swift Package Manager (SPM) gère la distribution des dépendances et des packages pour les projets Swift. Contrairement à CocoaPods ou Carthage, SPM s'intègre directement dans Xcode et la chaîne d'outils Swift, sans nécessiter d'installation externe. Swift 6.2 et 6.3 ont introduit des paramètres de sécurité mémoire stricts, l'isolation par défaut des acteurs et le nouveau système Swift Build, faisant de SPM le choix définitif pour le développement iOS moderne.

Fonctionnement de SPM

Swift Package Manager résout les dépendances, télécharge le code source, compile les modules et les lie au binaire final. Un seul fichier manifest Package.swift définit tout : dépendances, cibles, produits et paramètres de compilation.

Structure et Syntaxe du Manifest Package.swift

Chaque package Swift commence par un fichier Package.swift à la racine du dépôt. Ce manifest utilise du code Swift pour déclarer la structure du package, les dépendances et la configuration de compilation.

Package.swiftswift
import PackageDescription

let package = Package(
    name: "NetworkKit",
    platforms: [
        .iOS(.v15),
        .macOS(.v12)
    ],
    products: [
        .library(
            name: "NetworkKit",
            targets: ["NetworkKit"]
        )
    ],
    dependencies: [
        .package(
            url: "https://github.com/Alamofire/Alamofire.git",
            from: "5.9.0"
        )
    ],
    targets: [
        .target(
            name: "NetworkKit",
            dependencies: ["Alamofire"]
        ),
        .testTarget(
            name: "NetworkKitTests",
            dependencies: ["NetworkKit"]
        )
    ]
)

Le tableau platforms spécifie les cibles de déploiement minimales. La section products définit ce que les autres packages peuvent importer. La section targets liste les unités de compilation avec leurs dépendances respectives.

Créer un Package Swift en Ligne de Commande

La commande swift package init génère un nouveau package avec la structure de répertoires standard. Le flag --type détermine si le package produit une bibliothèque ou un exécutable.

bash
# Créer un package bibliothèque
mkdir NetworkKit && cd NetworkKit
swift package init --type=library

# Structure générée:
# NetworkKit/
# ├── Package.swift
# ├── Sources/
# │   └── NetworkKit/
# │       └── NetworkKit.swift
# └── Tests/
#     └── NetworkKitTests/
#         └── NetworkKitTests.swift

L'exécution de swift build compile le package. L'exécution de swift test lance la suite de tests. Les deux commandes utilisent la configuration de Package.swift sans configuration supplémentaire.

Spécification des Versions et Résolution des Dépendances

SPM prend en charge trois stratégies de spécification de version : version exacte, plage de versions et référence de branche ou commit. Le choix affecte la reproductibilité et la flexibilité.

Package.swiftswift
dependencies: [
    // Versioning sémantique : 5.9.0 jusqu'à la prochaine majeure
    .package(url: "https://github.com/Alamofire/Alamofire.git", from: "5.9.0"),
    
    // Version exacte : verrouillée sur 5.9.1
    .package(url: "https://github.com/Alamofire/Alamofire.git", exact: "5.9.1"),
    
    // Plage de versions : 5.8.0 à 5.9.9
    .package(url: "https://github.com/Alamofire/Alamofire.git", "5.8.0".."5.9.9"),
    
    // Référence de branche : pour le développement
    .package(url: "https://github.com/Alamofire/Alamofire.git", branch: "main"),
    
    // Référence de commit : épinglée à un commit spécifique
    .package(url: "https://github.com/Alamofire/Alamofire.git", revision: "abc123")
]

Le fichier Package.resolved enregistre les versions exactes résolues lors de la résolution des dépendances. Ce fichier doit être commité dans le contrôle de version pour des builds reproductibles entre les membres de l'équipe et les systèmes CI.

Dépendances de Branche en Production

Les références de branche et de commit contournent le versioning sémantique. Utiliser branch: "main" dans une application en production signifie que tout push sur main peut casser le build. Les références de branche doivent être réservées au développement actif contre des fonctionnalités non publiées.

Ajouter des Packages à un Projet Xcode

Xcode intègre SPM via le menu Fichier. Il suffit de naviguer vers Fichier, puis Add Package Dependencies. Entrer l'URL du dépôt, sélectionner la règle de version et choisir quelles cibles doivent lier la dépendance.

AppDelegate.swiftswift
import UIKit
import Alamofire // Disponible après ajout via Xcode

@main
class AppDelegate: UIResponder, UIApplicationDelegate {
    func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {
        AF.request("https://api.example.com/health").response { response in
            print(response.result)
        }
        return true
    }
}

Xcode stocke les références de packages dans le fichier .xcodeproj et les versions résolues dans Package.resolved à la racine du projet. Le dossier Derived Data met en cache les packages téléchargés.

Développement Local avec Dépendances de Chemin

Pendant le développement, pointer vers un chemin local au lieu d'une URL distante permet une itération rapide sans publier de versions intermédiaires. Cette technique convient aux configurations monorepo et au développement de fonctionnalités.

Package.swift dans le package consommateurswift
dependencies: [
    // Chemin local pour le développement
    .package(path: "../NetworkKit"),
    
    // URL distante pour la release
    // .package(url: "https://github.com/company/NetworkKit.git", from: "1.0.0")
]

Basculer entre les dépendances locales et distantes en commentant la ligne inactive. Xcode et le CLI Swift résolvent les dépendances de chemin relativement au package consommateur.

Prêt à réussir tes entretiens iOS ?

Entraîne-toi avec nos simulateurs interactifs, fiches express et tests techniques.

Publier un Package Swift sur GitHub

La publication nécessite un dépôt Git avec des tags de version sémantique. SPM traite les tags Git comme des versions de release. Le Swift Package Index indexe automatiquement les packages publics.

bash
# Initialiser le dépôt et pusher
git init
git add .
git commit -m "Initial commit"
git remote add origin https://github.com/username/NetworkKit.git
git push -u origin main

# Créer le tag de version
git tag 1.0.0
git push origin 1.0.0

# Les autres packages peuvent maintenant dépendre de:
# .package(url: "https://github.com/username/NetworkKit.git", from: "1.0.0")

Suivre les conventions du versioning sémantique : incrémenter la version majeure pour les changements cassants, mineure pour les nouvelles fonctionnalités, et patch pour les corrections de bugs. SPM suppose le respect de ces règles lors de la résolution des exigences de version from:.

Paramètres de Package Swift 6.2 et 6.3

Swift 6.2 a introduit la configuration du mode de langage par cible et les paramètres de sécurité mémoire stricts. Swift 6.3 ajoute l'intégration de Swift Build comme système de compilation optionnel.

Package.swift avec fonctionnalités Swift 6.2+swift
import PackageDescription

let package = Package(
    name: "SafeNetworkKit",
    platforms: [.iOS(.v17)],
    products: [
        .library(name: "SafeNetworkKit", targets: ["SafeNetworkKit"])
    ],
    targets: [
        .target(
            name: "SafeNetworkKit",
            swiftSettings: [
                // Activer le mode Swift 6 pour cette cible uniquement
                .swiftLanguageMode(.v6),
                // Activer la vérification stricte de sécurité mémoire (SE-0458)
                .enableExperimentalFeature("StrictMemorySafety"),
                // Définir l'isolation par défaut des acteurs (SE-0466)
                .enableExperimentalFeature("GlobalActorIsolation")
            ]
        )
    ]
)

Le paramètre swiftLanguageMode permet l'adoption progressive des fonctionnalités Swift 6 dans une base de code. Les cibles peuvent utiliser différents modes de langage au sein du même package.

Génération SBOM pour la Conformité de Sécurité

SE-0509 a ajouté la génération native de Software Bill of Materials dans Swift 6.3. Les documents SBOM listent toutes les dépendances et leurs versions pour l'audit de sécurité et la conformité réglementaire.

bash
# Générer SBOM au format CycloneDX
swift build --sbom-spec cyclonedx

# Générer SBOM avec la sous-commande dédiée
swift package generate-sbom --format spdx

# La sortie inclut:
# - Nom et version du package
# - Toutes les dépendances transitives
# - Informations de licence
# - URLs des dépôts source

Les environnements d'entreprise et les contrats gouvernementaux exigent de plus en plus la documentation SBOM. Les formats CycloneDX et SPDX s'intègrent aux outils standard d'analyse de vulnérabilités.

Cibles Binaires et Distribution XCFramework

Les cibles binaires permettent la distribution de frameworks précompilés au lieu du code source. Les XCFrameworks regroupent des binaires pour plusieurs plateformes et architectures.

Package.swift avec cible binaireswift
import PackageDescription

let package = Package(
    name: "AnalyticsSDK",
    platforms: [.iOS(.v14)],
    products: [
        .library(name: "AnalyticsSDK", targets: ["AnalyticsSDK"])
    ],
    targets: [
        .binaryTarget(
            name: "AnalyticsSDK",
            url: "https://releases.example.com/AnalyticsSDK-2.0.0.xcframework.zip",
            checksum: "abc123def456..."
        )
    ]
)

// Générer le checksum:
// swift package compute-checksum AnalyticsSDK-2.0.0.xcframework.zip

Les cibles binaires réduisent les temps de compilation pour les consommateurs et protègent les implémentations propriétaires. Le checksum garantit l'intégrité du téléchargement.

Questions d'Entretien Courantes sur Swift Package Manager

Les entretiens techniques pour les postes iOS incluent fréquemment des questions sur SPM. Celles-ci vont de l'utilisation de base aux décisions architecturales.

Q : Comment SPM diffère-t-il de CocoaPods et Carthage ?

SPM s'intègre dans Xcode et la chaîne d'outils Swift sans outils externes. CocoaPods utilise un dépôt de spécifications central et modifie la structure du workspace Xcode. Carthage compile les frameworks dans une étape séparée sans intégration Xcode. SPM résout les dépendances et compile dans un processus unifié unique. La documentation Apple sur les packages Swift couvre l'outillage officiel.

Q : Que se passe-t-il lors de la résolution des dépendances ?

SPM lit les manifests Package.swift récursivement, construisant un graphe de dépendances. Il applique ensuite les contraintes de version pour trouver des versions compatibles pour tous les packages. Le résolveur écrit les versions exactes dans Package.resolved. Les conflits surviennent lorsque deux packages nécessitent des versions incompatibles d'une dépendance partagée.

Q : Comment gérer un conflit de dépendance en diamant ?

Lorsque les packages A et B dépendent tous deux du package C avec des exigences de version incompatibles, la résolution SPM échoue. Les solutions incluent : mettre à jour un consommateur pour supporter une plage de versions plus large, forker le package restrictif, ou utiliser l'aliasing de module si le conflit est entre différents packages avec le même nom de module.

swift
// Aliasing de module pour les conflits de noms
.target(
    name: "MyApp",
    dependencies: [
        .product(name: "Logging", package: "swift-log", moduleAliases: ["Logging": "SwiftLogging"])
    ]
)

Q : Quand utiliser une cible binaire au lieu de la distribution source ?

Les cibles binaires conviennent aux SDKs propriétaires où l'exposition du code source est inacceptable, aux grandes dépendances où le temps de compilation affecte la productivité des développeurs, et aux bibliothèques vendor précompilées. La distribution source reste préférable pour les projets open source et les bibliothèques internes où le débogage dans les dépendances apporte de la valeur.

Migrer de CocoaPods vers Swift Package Manager

La migration nécessite de remplacer les entrées du Podfile par des références de packages SPM. Tous les CocoaPods n'ont pas d'équivalents SPM, il faut donc vérifier la disponibilité sur Swift Package Index avant de commencer.

ruby
# Avant: Podfile
pod 'Alamofire', '~> 5.9'
pod 'SwiftyJSON', '~> 5.0'
pod 'Kingfisher', '~> 7.0'
swift
// Après: Dépendances de packages dans Xcode
// File > Add Package Dependencies pour chaque:
// https://github.com/Alamofire/Alamofire.git from 5.9.0
// https://github.com/SwiftyJSON/SwiftyJSON.git from 5.0.0
// https://github.com/onevcat/Kingfisher.git from 7.0.0

Supprimer le Podfile, Podfile.lock et le répertoire Pods après la migration. Exécuter pod deintegrate pour supprimer les modifications du workspace CocoaPods. Les instructions d'import dans les fichiers Swift restent inchangées.

Bonnes Pratiques SPM pour les Applications en Production

  • Épingler les versions majeures avec from: pour la stabilité tout en recevant les mises à jour mineures et les patchs
  • Commiter Package.resolved pour assurer des builds reproductibles dans l'équipe
  • Utiliser des packages locaux pendant le développement actif, en passant aux URLs distantes avant de merger
  • Séparer les dépendances de test uniquement avec testTarget pour éviter de les inclure dans les builds de release
  • Documenter la version minimale des outils Swift en haut du manifest : // swift-tools-version: 5.10
  • Valider les builds de packages sur la CI avant de tagger les releases
Version des Outils Swift

Le commentaire // swift-tools-version: doit apparaître sur la première ligne de Package.swift. Il détermine quelle version de l'API PackageDescription le manifest utilise. Swift 6.0 a ajouté la flexibilité de permettre ce commentaire sur les lignes suivantes pour les en-têtes de licence.

Points Clés pour les Développeurs iOS Utilisant SPM

  • SPM s'intègre nativement dans Xcode, éliminant les surcharges de configuration de CocoaPods et Carthage
  • Le manifest Package.swift utilise du code Swift, permettant des déclarations de dépendances vérifiées par le typage
  • Les exigences de version supportent les plages de versioning sémantique, les versions exactes et les références de branches
  • Package.resolved verrouille les versions des dépendances pour des builds reproductibles
  • Swift 6.2 a ajouté les modes de langage par cible et les paramètres de sécurité mémoire stricts
  • Swift 6.3 a introduit la génération SBOM pour la documentation de conformité
  • Les cibles binaires distribuent des XCFrameworks précompilés quand la distribution source est impraticable
  • Les questions d'entretien se concentrent sur les conflits de résolution, les stratégies de migration et les compromis architecturaux entre SPM et les alternatives

Pour une préparation complète aux entretiens iOS, consulter les modules sur la gestion d'état SwiftUI et la programmation orientée protocoles sur SharpSkill.

Passe à la pratique !

Teste tes connaissances avec nos simulateurs d'entretien et tests techniques.

Défi du jour

Tu saurais repérer le bug en iOS ?

Un vrai bout de code, un bug caché, une tentative par jour. Sans compte pour essayer.

Anthony Fillion-Maillet

Écrit par

Anthony Fillion-Maillet

Fondateur de SharpSkill

Développeur fullstack depuis plus de 10 ans. Il dirige SharpSkill et répond de tout ce qui y est publié.

Mis à jour le 20 septembre 2026

Partager

Articles similaires