SPM (Swift Package Manager) ist ein integrierter Paketmanager des Swift-Ökosystems, der von Apple entwickelt wurde, um das Hinzufügen, Bauen und Aktualisieren von Drittanbieter-Bibliotheken zu automatisieren. SPM ist seit Version 3.0 (2016) Teil des Swift-Compilers und erfordert keine separate Installation. Im Gegensatz zu CocoaPods und Carthage ist SPM direkt in den Compiler und Xcode integriert, was es zum Standardwerkzeug für die Abhängigkeitsverwaltung in modernen Swift-Projekten macht. In diesem Artikel beleuchten wir die Struktur von Package.swift, SPM-Befehle, das Erstellen eigener Pakete und die Migration von alternativen Managern.
Wichtige Punkte
SPM (Swift Package Manager) ist der offizielle Paketmanager für die Sprache Swift, integriert in den swiftc-Compiler und die Entwicklungsumgebung Xcode. Er ermöglicht Entwicklern das Hinzufügen von Drittanbieter-Bibliotheken, die Verwaltung ihrer Versionen und das Veröffentlichen eigener Pakete. SPM erschien erstmals in Swift 3.0 (September 2016) als Befehlszeilenwerkzeug und erhielt ab Xcode 11 (2019) vollständige Integration in die grafische Oberfläche — Abhängigkeiten werden nun über das Menü File → Add Packages hinzugefügt.
SPM lädt automatisch den Quellcode von Abhängigkeiten aus Git-Repositories herunter, baut sie parallel zum Hauptprojekt und cached die Ergebnisse, sodass nachfolgende Builds schneller ausgeführt werden. Im Gegensatz zu CocoaPods erzeugt SPM keinen separaten Workspace (xcworkspace) — die Abhängigkeiten werden Teil des Haupt-Xcode-Projekts. Laut der Swift.org Developer Survey (2024) verwenden 67% der iOS-Entwickler SPM, was es zum beliebtesten Abhängigkeitsverwaltungstool im Swift-Ökosystem macht.
SPM unterstützt drei Plattformen: Apple (iOS, macOS, tvOS, watchOS, visionOS), Linux (Ubuntu, CentOS, Amazon Linux) und serverseitiges Swift (Vapor, Kitura). Unter Linux funktioniert SPM vollständig über die Befehlszeile ohne Xcode.
SPM basiert auf drei Schlüsselkonzepten: Paketen (packages), Produkten (products) und Zielen (targets). Ein Paket ist ein Git-Repository mit einem Package.swift-Manifest. Ein Produkt ist das Buildergebnis (eine Bibliothek oder eine ausführbare Datei). Ein Ziel ist ein Modul innerhalb des Pakets, das zu einer Baueinheit kompiliert wird.
Wenn ein Entwickler eine Abhängigkeit zu Package.swift hinzufügt, führt SPM die folgenden Schritte aus:
~Library/Caches/org.swift.swiftpm/.Die Datei Package.resolved fixiert die exakten Versionen aller Abhängigkeiten, sodass das Entwicklungsteam mit einem identischen Satz von Bibliotheken arbeitet. Diese Datei sollte zur Versionskontrolle (git) hinzugefügt werden.
Ein wesentlicher Vorteil von SPM gegenüber Alternativen ist das Fehlen einer zentralen Registry. Pakete können in jedem öffentlichen Git-Repository liegen: GitHub, GitLab, Bitbucket, sowie auf unternehmenseigenen Git-Servern. Seit Swift 5.2 unterstützt SPM binäre Abhängigkeiten (binary targets) — Closed-Source-Bibliotheken, die als XCFramework ohne Quellcode verteilt werden.
Package.swift ist eine Swift-Datei, die die Paketstruktur und ihre Abhängigkeiten beschreibt. Die Datei ist in Swift selbst geschrieben (nicht JSON oder YAML), was die Verwendung von Bedingungslogik, berechneten Konstanten und Funktionen innerhalb des Manifests ermöglicht.
Grundstruktur von Package.swift:
// swift-tools-version: 5.9
import PackageDescription
let package = Package(
name: "MyLibrary",
platforms: [
.iOS(.v16),
.macOS(.v13)
],
products: [
.library(
name: "MyLibrary",
targets: ["MyLibrary"]
),
],
dependencies: [
.package(url: "https://github.com/Alamofire/Alamofire.git",
from: "5.9.0"),
.package(url: "https://github.com/onevcat/Kingfisher.git",
from: "7.12.0"),
],
targets: [
.target(
name: "MyLibrary",
dependencies: [
"Alamofire",
"Kingfisher"
]
),
.testTarget(
name: "MyLibraryTests",
dependencies: ["MyLibrary"]
),
]
)
Lassen Sie uns die Schlüsselelemente analysieren:
// swift-tools-version: 5.9 — Direktive, die die SPM-Version angibt; davon hängt die verfügbare Manifestsyntax ab.name — der Paketname, der in Xcode angezeigt und in Abhängigkeitslinks verwendet wird.platforms — minimale Plattformversionen; SPM erlaubt das Bauen des Pakets auf einer älteren OS-Version nicht.products — was das Paket exportiert: eine Bibliothek (.library) oder eine ausführbare Datei (.executable).dependencies — Liste externer Pakete mit URL und Version; unterstützt from:, exact:, branch:, revision:.targets — Bauziele; jedes Ziel enthält eine Liste von Abhängigkeiten, Ressourcen und Swift-Dateien aus dem entsprechenden Verzeichnis (Sources/TargetName/).Beispiel für die Angabe einer genauen Version, Branch und Commit:
dependencies: [
.package(url: "https://github.com/pointfreeco/swift-snapshot-testing.git",
exact: "1.17.3"),
.package(url: "https://github.com/pointfreeco/swift-composable-architecture.git",
branch: "main"),
.package(url: "https://github.com/apple/swift-log.git",
revision: "e5c6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4"),
]
Seit Swift 5.9 wurde in Package.swift Unterstützung für static framework und linkerSettings hinzugefügt, was eine präzisere Linkerkonfiguration für statische und dynamische Bibliotheken ermöglicht.
Swift Package Manager bietet eine Reihe von Befehlen für die Arbeit über das Terminal. Die Befehle werden aus dem Stammverzeichnis des Pakets (wo Package.swift liegt) ausgeführt.
# Neues Paket mit einer Bibliothek erstellen
swift package init --type library
# Ausführbares Paket erstellen (Konsolenanwendung)
swift package init --type executable
# Projekt bauen
swift build
# In Release-Konfiguration bauen
swift build -c release
# Tests ausführen
swift test
# Bestimmten Test ausführen
swift test --filter "MyLibraryTests/testExample"
# Abhängigkeiten herunterladen und auflösen
swift package resolve
# Abhängigkeiten auf die neuesten verfügbaren Versionen aktualisieren
swift package update
# Abhängigkeitsgraphen anzeigen
swift package show-dependencies
# Build-Cache leeren
swift package clean
# Xcode-Projekt generieren (vor Xcode 11)
swift package generate-xcodeproj
Bei der Arbeit in Xcode werden die meisten dieser Befehle automatisch ausgeführt: Abhängigkeiten werden beim Öffnen des Projekts aufgelöst, der Build startet mit ⌘B, Tests mit ⌘U. Die Kenntnis der Terminalbefehle ist jedoch für CI/CD-Pipelines (GitHub Actions, GitLab CI, Jenkins) erforderlich, wo Xcode nicht verfügbar ist.
Der Befehl swift package resolve erstellt oder aktualisiert die Datei Package.resolved. Diese Datei fixiert die exakten Versionen aller Abhängigkeiten, einschließlich transitiver, und sollte zu git hinzugefügt werden. Es wird empfohlen, vor jedem neuen Feature-Branch swift package update auszuführen, um mit aktuellen Bibliotheksversionen zu arbeiten.
Das Erstellen eigener SPM-Pakete ist nützlich, um Geschäftslogik in Multi-Modul-Projekten zu kapseln und Open-Source-Bibliotheken zu veröffentlichen. Sehen wir uns den schrittweisen Prozess an.
mkdir MyNetworkKit
cd MyNetworkKit
swift package init --type library
Der Befehl swift package init erstellt die folgende Struktur:
MyNetworkKit/
├── Package.swift
├── README.md
├── Sources/
│ └── MyNetworkKit/
│ └── MyNetworkKit.swift
└── Tests/
└── MyNetworkKitTests/
└── MyNetworkKitTests.swift
SPM durchsucht automatisch die Verzeichnisse Sources/ und Tests/: jedes Unterverzeichnis in Sources entspricht einem Ziel (target).
Fügen wir Abhängigkeiten hinzu und konfigurieren die Zielplattformen:
// swift-tools-version: 5.9
import PackageDescription
let package = Package(
name: "MyNetworkKit",
platforms: [
.iOS(.v15),
.macOS(.v12)
],
products: [
.library(
name: "MyNetworkKit",
targets: ["MyNetworkKit"]
),
],
dependencies: [
.package(url: "https://github.com/Alamofire/Alamofire.git",
from: "5.9.0"),
],
targets: [
.target(
name: "MyNetworkKit",
dependencies: ["Alamofire"]
),
.testTarget(
name: "MyNetworkKitTests",
dependencies: ["MyNetworkKit"]
),
]
)
// Sources/MyNetworkKit/MyNetworkKit.swift
import Foundation
import Alamofire
public struct NetworkClient {
private let session: Session
public init() {
let configuration = URLSessionConfiguration.default
configuration.timeoutIntervalForRequest = 30
self.session = Session(configuration: configuration)
}
public func fetchData(from url: String) async throws -> Data {
let response = try await session.request(url).serializingData().value
return response
}
}
Schieben Sie das Paket in ein Git-Repository und erstellen Sie einen SemVer-Tag:
git init
git add .
git commit -m "Initial commit: MyNetworkKit"
git remote add origin https://github.com/username/MyNetworkKit.git
git push -u origin main
git tag 1.0.0
git push --tags
Danach kann jeder Entwickler Ihr Paket mit .package(url: "https://github.com/username/MyNetworkKit.git", from: "1.0.0") hinzufügen.
Alamofire ist der beliebteste HTTP-Client für Swift. Fügen wir ihn über SPM hinzu und führen eine GET-Anfrage aus.
import Alamofire
func fetchUsers() {
AF.request("https://jsonplaceholder.typicode.com/users")
.validate()
.responseDecodable(of: [User].self) { response in
switch response.result {
case .success(let users):
print("(users.count) Benutzer empfangen")
case .failure(let error):
print("Fehler: (error.localizedDescription)")
}
}
}
Die Bibliothek Swinject bietet einen DI-Container für Swift. Sie wird hinzugefügt über .package(url: "https://github.com/Swinject/Swinject.git", from: "2.8.0").
import Swinject
let container = Container()
container.register(NetworkServiceProtocol.self) { _ in NetworkService() }
container.register(DataRepositoryProtocol.self) { r in
DataRepository(networkService: r.resolve(NetworkServiceProtocol.self)!)
}
let repository = container.resolve(DataRepositoryProtocol.self)
repository?.loadData()
Das swift-log-Paket von Apple bietet eine einheitliche Logging-API, die mehrere Backends unterstützt (OSLog, Konsole, Dateien).
import Logging
var logger = Logger(label: "com.myapp.network")
logger.logLevel = .debug
logger.info("Netzwerkanfrage gestartet", metadata: [
"url": "(requestURL)",
"method": "GET"
])
logger.warning("Antwortzeit überschritt 2 Sekunden")
logger.error("Verbindungsfehler: Kein Internet")
Diese drei Beispiele decken typische SPM-Anwendungsszenarien ab: HTTP-Clients, DI-Container und Systeminfrastruktur. Die Auswahl der Bibliotheken ist nicht zufällig — Alamofire, Swinject und swift-log gehören zu den 20 meistgestarnten Swift-Paketen auf GitHub.
Wenn Ihr Projekt CocoaPods oder Carthage verwendet, erfolgt die Migration zu SPM in wenigen Schritten. Der Prozess ist sicher: SPM-Abhängigkeiten können im selben Projekt mit CocoaPods und Carthage koexistieren, was eine schrittweise Migration ermöglicht.
.xcworkspace, öffnen Sie das .xcodeproj und führen Sie Clean Build Folder aus.rm -rf Carthage/ im Terminal.Stand 2025 unterstützt SPM die überwiegende Mehrheit der populären Swift-Bibliotheken. Ausnahmen sind einige ObjC-Frameworks ohne Modulmaps. Wenn eine Bibliothek SPM noch nicht unterstützt — überprüfen Sie den Abschnitt Installation in ihrer README; die meisten Autoren haben bereits SPM-Unterstützung in den neuesten Versionen hinzugefügt.
Häufig gestellte Fragen
SPM ist in den Swift-Compiler und Xcode integriert und erfordert keine Installation über gem oder Homebrew. CocoaPods verwendet eine zentrale Specs-Registry und erzeugt einen separaten Workspace. Carthage arbeitet über Frameworks ohne Projektintegration. SPM ist der einzige Manager, der auf Compiler-Ebene integriert ist: Abhängigkeiten werden parallel zum Hauptcode aufgelöst, gecached und gebaut.
Ja, SPM unterstützt gemischte Swift + Objective-C-Projekte. ObjC-Dateien innerhalb eines SPM-Pakets werden automatisch in einen Umbrella Header aufgenommen, sofern ein korrektes modulemap existiert. Allerdings unterstützt SPM keine statischen ObjC-Bibliotheken ohne Modulmap. Es wird empfohlen, ObjC-Bibliotheken nur dann über SPM anzubinden, wenn sie eine modulemap bereitstellen oder in reinem C geschrieben sind.
SPM verwendet semantische Versionierung (SemVer). Wenn Paket A Alamofire 5.8+ benötigt und Paket B Alamofire 5.9+ benötigt, wählt SPM die Version 5.9.x, die beide Anforderungen erfüllt. Ist der Konflikt nicht auflösbar (ein Paket benötigt 5.x, ein anderes 6.x), meldet SPM einen Fehler. In diesem Fall müssen Sie eines der Pakete aktualisieren oder die Abhängigkeit auf eine mit beiden Anforderungen kompatible Version umstellen.
Unter macOS: ~Library/Caches/org.swift.swiftpm/ und ~/Library/Developer/Xcode/DerivedData/. Unter Linux: ~cache/swiftpm/. Während des Bauens cached SPM Quellcode und kompilierte Objektdateien. Zum vollständigen Leeren des Caches führen Sie swift package reset aus — dieser Befehl entfernt den Abhängigkeits-Cache und DerivedData für das aktuelle Projekt.
Ja, seit Swift 5.2 unterstützt SPM binäre Ziele (binary targets). Eine Closed-Source-Bibliothek wird als XCFramework verteilt, und der Pfad zur .xcframework wird in Package.swift angegeben. Der Quellcode wird nicht offengelegt. Ein binäres Ziel wird angegeben über .binaryTarget(name: "PrivateSDK", path: "Sources/PrivateSDK.xcframework"). Dies ermöglicht die Anbindung kommerzieller SDKs ohne Verletzung von Lizenzvereinbarungen.
Zusammenfassung
Wir entwickeln eine mobile Applikation schlüsselfertig
IT Sectr entwickelt seit 2017 iOS- und Android-Apps für Startups und Unternehmen. Wir beraten Sie und schlagen die beste Lösung vor.
Lesen Sie auch