SPM (Swift Package Manager) — den inbyggda pakethanteraren i Swift-ekosystemet, utvecklad av Apple för att automatisera anslutning, byggande och uppdatering av tredjepartsbibliotek. SPM har ingått i Swift-kompilatorn sedan version 3.0 (2016) och kräver ingen separat installation. Till skillnad från CocoaPods och Carthage är SPM direkt integrerad med kompilatorn och Xcode, vilket gör det till standardverktyget för beroendehantering i moderna Swift-projekt. I artikeln kommer vi att gå igenom strukturen för Package.swift, SPM-kommandon, skrivning av egna paket och migrering från alternativa hanterare.
Huvudpunkter
SPM (Swift Package Manager) — den officiella pakethanteraren för programmeringsspråket Swift, inbyggd i swiftc-kompilatorn och Xcode-utvecklingsmiljön. Den låter utvecklare ansluta tredjepartsbibliotek, hantera deras versioner och publicera egna paket. SPM dök först upp i Swift 3.0 (september 2016) som ett kommandoradsverktyg och fick från Xcode 11 (2019) full integration med det grafiska gränssnittet — nu läggs beroenden till via menyn File → Add Packages.
SPM laddar automatisnera ned källkoden för beroenden från Git-förvar, bygger dem parallellt med huvudprojektet och cachelagrar resultaten så att återuppbyggnader går snabbare. Till skillnad från CocoaPods genererar SPM ingen separat arbetsyta (xcworkspace) — beroendena blir en del av huvudprojektet i Xcode. Enligt Swift.org Developer Survey (2024) använder 67% av iOS-utvecklarna SPM, vilket gör det till det populäraste verktyget för beroendehantering i Swift-ekosystemet.
SPM stöder tre plattformar: Apple (iOS, macOS, tvOS, watchOS, visionOS), Linux (Ubuntu, CentOS, Amazon Linux) och server-Swift (Vapor, Kitura). På Linux fungerar SPM helt via kommandoraden utan Xcode.
SPM är uppbyggt kring tre nyckelkoncept: paket (packages), produkter (products) och mål (targets). Ett paket är ett Git-förvar med manifestet Package.swift. En produkt är byggresultatet (bibliotek eller körbar fil). Ett mål är en modul inom paketet som kompileras till en byggenhet.
När en utvecklare lägger till ett beroende i Package.swift utför SPM följande steg:
~Library/Caches/org.swift.swiftpm/.Filen Package.resolved fastställer exakta versioner av alla beroenden så att utvecklingsteamet arbetar med identisk uppsättning bibliotek. Denna fil bör läggas till i versionshanteringssystemet (git).
Den främsta fördelen med SPM jämfört med alternativen — ingen centraliserad register. Paket kan finnas i vilket offentligt Git-förvar som helst: GitHub, GitLab, Bitbucket, samt på företagets egna Git-servrar. Från och med Swift 5.2 stöder SPM binära beroenden (binary targets) — stängda bibliotek som distribueras via XCFramework utan att tillhandahålla källkod.
Package.swift — är en Swift-fil som beskriver paketets struktur och dess beroenden. Filen skrivs i Swift självt (inte JSON, inte YAML), vilket gör det möjligt att använda villkorslogik, beräknade konstanter och funktioner inuti manifestet.
Grundläggande struktur för 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"]
),
]
)
Låt oss gå igenom nyckelelementen:
// swift-tools-version: 5.9 — direktiv som anger SPM-versionen; manifestets tillgängliga syntax beror på detta.name — paketnamnet som visas i Xcode och används i beroendereferenser.platforms — minimiversioner av plattformar; SPM tillåter inte att paketet byggs på en äldre OS-version.products — vad paketet "exporterar": bibliotek (.library) eller körbar fil (.executable).dependencies — lista över externa paket med URL och version; from:, exact:, branch:, revision: stöds.targets — byggmål; varje mål innehåller en lista över beroenden, resurser och swift-filer från motsvarande katalog (Sources/TargetName/).Exempel på angivande av exakt version, gren och 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"),
]
Från och med Swift 5.9 har stöd för static/framework och linkerSettings lagts till i Package.swift, vilket möjliggör mer exakt konfiguration av länkning för statiska och dynamiska bibliotek.
Swift Package Manager tillhandahåller en uppsättning kommandon för arbete via terminalen. Kommandon körs från paketets rotkatalog (där Package.swift finns).
# Skapa ett nytt paket med bibliotek
swift package init --type library
# Skapa ett körbart paket (konsolapplikation)
swift package init --type executable
# Bygg projektet
swift build
# Bygg i release-konfiguration
swift build -c release
# Kör testerna
swift test
# Kör ett specifikt test
swift test --filter "MyLibraryTests/testExample"
# Ladda ner och lös beroenden
swift package resolve
# Uppdatera beroenden till senaste tillgängliga versioner
swift package update
# Visa beroendegrafen
swift package show-dependencies
# Rensa byggcachen
swift package clean
# Generera Xcode-projekt (före Xcode 11)
swift package generate-xcodeproj
När du arbetar i Xcode utförs de flesta av dessa kommandon automatiskt: beroenden löses när projektet öppnas, byggning startas med ⌘B, tester med ⌘U. Kännedom om terminalkommandon är dock nödvändig för CI/CD-pipelines (GitHub Actions, GitLab CI, Jenkins), där Xcode inte är tillgängligt.
Kommandot swift package resolve skapar eller uppdaterar filen Package.resolved. Denna fil fastställer exakta versioner av alla beroenden, inklusive transitiva, och bör läggas till i git. Det rekommenderas att köra swift package update före varje ny feature-gren för att arbeta med aktuella biblioteksversioner.
Att skapa ett eget SPM-paket är användbart för inkapsling av affärslogik i multimodulprojekt och för publicering av open-source-bibliotek. Låt oss gå igenom processen steg för steg.
mkdir MyNetworkKit
cd MyNetworkKit
swift package init --type library
Kommandot swift package init skapar följande struktur:
MyNetworkKit/
├── Package.swift
├── README.md
├── Sources/
│ └── MyNetworkKit/
│ └── MyNetworkKit.swift
└── Tests/
└── MyNetworkKitTests/
└── MyNetworkKitTests.swift
SPM skannar automatiskt katalogerna Sources/ och Tests/: varje underkatalog i Sources motsvarar ett mål (target).
Lägg till beroenden och konfigurera målplattformarna:
// 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
}
}
Pusha paketet till Git-förvaret och skapa en SemVer-tagg:
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
Efter detta kan vilken utvecklare som helst ansluta ditt paket via .package(url: "https://github.com/username/MyNetworkKit.git", from: "1.0.0").
Alamofire — den populäraste HTTP-klienten för Swift. Låt oss lägga till den via SPM och utföra en GET-förfrågan.
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) användare mottagna")
case .failure(let error):
print("Fel: \(error.localizedDescription)")
}
}
}
Swinject-biblioteket tillhandahåller en DI-container för Swift. Ansluts via .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()
Swift-log-paketet från Apple — ett enhetligt loggnings-API som stöder flera backend (OSLog, konsol, filer).
import Logging
var logger = Logger(label: "com.myapp.network")
logger.logLevel = .debug
logger.info("Nätverksförfrågan påbörjad", metadata: [
"url": "\(requestURL)",
"method": "GET"
])
logger.warning("Svarstiden översteg 2 sekunder")
logger.error("Anslutningsfel: inget internet")
Dessa tre exempel täcker typiska SPM-användningsscenarier: HTTP-klienter, DI-containrar och systeminfrastruktur. Valet av bibliotek är inte slumpmässigt — Alamofire, Swinject och swift-log finns bland de 20 mest populära Swift-paketen på GitHub.
Om projektet använder CocoaPods eller Carthage görs migreringen till SPM i några steg. Processen är säker: SPM-beroenden kan samexistera med CocoaPods och Carthage i samma projekt, vilket möjliggör gradvis migrering.
.xcworkspace, öppna .xcodeproj och utför Clean Build Folder.rm -rf Carthage/ i terminalen.Från och med 2025 stöder SPM de allra flesta populära Swift-biblioteken. Undantag är vissa ObjC-ramverk utan modulkartor (modulemap). Om ett bibliotek ännu inte stöder SPM — kontrollera avsnittet Installation i dess README; de flesta författare har redan lagt till SPM-stöd i de senaste versionerna.
Vanliga frågor
SPM är inbyggd i Swift-kompilatorn och Xcode, kräver ingen installation via gem eller Homebrew. CocoaPods använder ett centraliserat Specs-register och genererar en separat arbetsyta. Carthage fungerar via ramverk utan integration med projektet. SPM är den enda hanteraren som är integrerad på kompilatornivå: beroenden löses, cachelagras och byggs parallellt med huvudkoden.
Ja, SPM stöder blandade Swift + Objective-C-projekt. ObjC-filer inom SPM-paketet hamnar automatiskt i Umbrella Header under förutsättning av korrekt modulemap. SPM stöder dock inte statiska ObjC-bibliotek som saknar modulkarta. Det rekommenderas att ansluta ObjC-bibliotek via SPM endast om de tillhandahåller modulemap eller är skrivna i ren C.
SPM använder semantisk versionshantering (SemVer). Om paket A kräver Alamofire 5.8+ och paket B kräver Alamofire 5.9+, väljer SPM version 5.9.x som uppfyller båda. Om konflikten är olöslig (ett paket kräver 5.x, ett annat 6.x) rapporterar SPM ett fel. I så fall måste du uppdatera ett av paketen eller ändra beroendet till en version som är kompatibel med båda kraven.
På macOS: ~Library/Caches/org.swift.swiftpm/ och ~/Library/Developer/Xcode/DerivedData/. På Linux: ~cache/swiftpm/. Vid byggning cachelagrar SPM källkod och kompilerade objektfiler. För att rensa cachen helt, kör swift package reset — detta kommando tar bort beroendecachen och DerivedData för det aktuella projektet.
Ja, från och med Swift 5.2 stöder SPM binära mål (binary targets). Det stängda biblioteket levereras som XCFramework, och i Package.swift anges sökvägen till .xcframework. Källkoden avslöjas inte. Binärt mål anges via .binaryTarget(name: "PrivateSDK", path: "Sources/PrivateSDK.xcframework"). Detta gör det möjligt att ansluta kommersiella SDK:er utan att bryta licensavtal.
Sammanfattning
Vi utvecklar en mobil applikation nyckelfärdigt
IT Sectr skapar iOS- och Android-applikationer för startups och företag sedan 2017. Vi ger dig råd och föreslår den bästa lösningen.
Läs också