SPM: vad är det, Swift Package Manager och Package.swift

Författare: IT Sectr Publicerad: 2026-02-13 Lästid: 11 min

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) — inbyggd pakethanterare i Swift-kompilatorn, som inte kräver separat installation; fungerar på iOS, macOS, Linux och serverplattformar.
  • Package.swift — manifestfil som beskriver paketnamnet, plattformar, beroenden och målmoduler (targets) i deklarativt format.
  • SPM löser beroenden enligt semantisk versionshantering (SemVer), cachelagrar källkod och bygger paket parallellt för snabbhet.
  • Kommandon: swift package init (skapa paket), swift package update (uppdatera beroenden), swift build (bygga), swift test (köra tester).
  • Migrering från CocoaPods/Carthage till SPM görs via Xcode: File → Add Package Dependency, varefter podfile och Cartfile tas bort.

Vad är SPM?

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.

Hur Swift Package Manager fungerar

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:

  1. Kloning — SPM laddar ned beroendets Git-förvar från den angivna URL:en.
  2. Versionslösning — analyserar SemVer-taggar (t.ex. 2.1.3) och väljer lämplig version inom det angivna intervallet.
  3. Transitiv lösning — kontrollerar beroendenas beroenden och bygger en graf utan versionskonflikter.
  4. Cachelagring — sparar nedladdad källkod i ~Library/Caches/org.swift.swiftpm/.
  5. Kompilering — bygger alla mål i paketet med huvudprojektets flaggor.

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 — projektmanifest

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
// 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:

swift
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.

Grundläggande SPM-kommandon

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).

bash
# 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.

Skapa ett eget paket

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.

Steg 1: Initiering

bash
mkdir MyNetworkKit
cd MyNetworkKit
swift package init --type library

Steg 2: Katalogstruktur

Kommandot swift package init skapar följande struktur:

text
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).

Steg 3: Redigera Package.swift

Lägg till beroenden och konfigurera målplattformarna:

swift
// 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"]
        ),
    ]
)

Steg 4: Skriva kod

swift
// 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
    }
}

Steg 5: Publicering

Pusha paketet till Git-förvaret och skapa en SemVer-tagg:

bash
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").

Exempel på SPM-användning

Exempel 1: Ansluta Alamofire för nätverksförfrågningar

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.

swift
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)")
            }
        }
}

Exempel 2: Swinject — beroendeinjektion

Swinject-biblioteket tillhandahåller en DI-container för Swift. Ansluts via .package(url: "https://github.com/Swinject/Swinject.git", from: "2.8.0").

swift
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()

Exempel 3: Swift-log för strukturerad loggning

Swift-log-paketet från Apple — ett enhetligt loggnings-API som stöder flera backend (OSLog, konsol, filer).

swift
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.

Migrering från CocoaPods och Carthage

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.

CocoaPods → SPM

  1. I Xcode: File → Add Package Dependency, ange paketets URL.
  2. Välj version och lägg till paketet till önskade targets.
  3. Efter att ha lagt till alla beroenden via SPM, ta bort raderna från Podfile.
  4. Ta bort .xcworkspace, öppna .xcodeproj och utför Clean Build Folder.

Carthage → SPM

  1. Lägg till paket via Xcode File → Add Package Dependency.
  2. Ta bort beroenden från Cartfile.
  3. Ta bort Carthage-byggskript från Build Phases.
  4. Rensa cachen: 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

Vad skiljer SPM från CocoaPods och Carthage?

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.

Kan SPM användas för Objective-C-projekt?

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.

Hur löser SPM versionskonflikter?

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.

Var lagras nedladdade SPM-paket?

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.

Stöder SPM stängda (proprietära) bibliotek?

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

  • SPM (Swift Package Manager) — inbyggd Swift-pakethanterare som inte kräver separat installation och är integrerad med Xcode och kompilatorn.
  • Package.swift — deklarativt manifest i Swift som beskriver paketnamn, plattformar, beroenden, produkter och byggmål.
  • SPM använder Git-förvar som paketkälla och löser versioner enligt SemVer, cachelagrar källkod för snabbare återuppbyggnader.
  • Grundläggande kommandon: swift package init (skapa paket), swift build (bygga), swift test (testa), swift package update (uppdatera beroenden).
  • Eget paket skapas via swift package init, publiceras i Git och är tillgängligt för andra projekt via URL med SemVer-tagg.
  • Migrering från CocoaPods/Carthage till SPM är säker: beroenden kan samexistera, migrering görs via File → Add Package Dependency i Xcode.
  • SPM — standarden för beroendehantering i Swift-ekosystemet, använd av 67% av iOS-utvecklarna (Swift.org Developer Survey, 2024).

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.

Diskutera projektet

Läs också