SPM: ce este, Swift Package Manager și Package.swift

Autor: IT Sectr Publicat: 2026-02-13 Timp de citire: 11 min

SPM (Swift Package Manager) — managerul de pachete încorporat al ecosistemului Swift, dezvoltat de Apple pentru automatizarea conectării, construirii și actualizării bibliotecilor terțe. SPM face parte din compilatorul Swift începând cu versiunea 3.0 (2016) și nu necesită instalare separată. Spre deosebire de CocoaPods și Carthage, SPM este integrat direct cu compilatorul și Xcode, ceea ce îl face instrumentul standard de gestionare a dependențelor în proiectele Swift moderne. În articol vom analiza structura Package.swift, comenzile SPM, scrierea propriilor pachete și migrarea de la managerii alternativi.

Principalele puncte

  • SPM (Swift Package Manager) — manager de pachete încorporat în compilatorul Swift, care nu necesită instalare separată; funcționează pe iOS, macOS, Linux și platforme server.
  • Package.swift — fișier manifest care descrie numele pachetului, platformele, dependențele și modulele țintă (targets) în format declarativ.
  • SPM rezolvă dependențele după versionarea semantică (SemVer), stochează în cache codul sursă și construiește pachetele în paralel pentru accelerare.
  • Comenzi: swift package init (creează pachet), swift package update (actualizează dependențe), swift build (construiește), swift test (rulează teste).
  • Migrarea de la CocoaPods/Carthage la SPM se face prin Xcode: File → Add Package Dependency, după care podfile și Cartfile sunt șterse.

Ce este SPM?

SPM (Swift Package Manager) — managerul oficial de pachete pentru limbajul Swift, încorporat în compilatorul swiftc și mediul de dezvoltare Xcode. Acesta permite dezvoltatorilor să conecteze biblioteci terțe, să gestioneze versiunile acestora și să publice propriile pachete. SPM a apărut pentru prima dată în Swift 3.0 (septembrie 2016) ca instrument de linie de comandă, iar începând cu Xcode 11 (2019) a primit integrare completă cu interfața grafică — acum dependențele se adaugă prin meniul File → Add Packages.

SPM descarcă automat codul sursă al dependențelor din depozitele Git, le construiește în paralel cu proiectul principal și stochează în cache rezultatele pentru ca recompilările să fie mai rapide. Spre deosebire de CocoaPods, SPM nu generează un workspace separat (xcworkspace) — dependențele devin parte a proiectului principal Xcode. Conform sondajului Swift.org Developer Survey (2024), SPM este utilizat de 67% dintre dezvoltatorii iOS, ceea ce îl face cel mai popular instrument de gestionare a dependențelor în ecosistemul Swift.

SPM suportă trei platforme: Apple (iOS, macOS, tvOS, watchOS, visionOS), Linux (Ubuntu, CentOS, Amazon Linux) și Swift server (Vapor, Kitura). Pe Linux, SPM funcționează complet prin linie de comandă fără Xcode.

Cum funcționează Swift Package Manager

SPM este construit în jurul a trei concepte cheie: pachete (packages), produse (products) și ținte (targets). Un pachet este un depozit Git cu manifestul Package.swift. Un produs este rezultatul compilării (bibliotecă sau fișier executabil). O țintă este un modul în cadrul pachetului care se compilează într-o unitate de construcție.

Când un dezvoltator adaugă o dependență în Package.swift, SPM execută următorii pași:

  1. Clonare — SPM descarcă depozitul Git al dependenței de la URL-ul specificat.
  2. Rezolvarea versiunilor — analizează tag-urile SemVer (de exemplu, 2.1.3) și selectează versiunea potrivită în intervalul specificat.
  3. Rezolvare tranzitivă — verifică dependențele dependențelor și construiește un graf fără conflicte de versiuni.
  4. Stocare în cache — salvează codul sursă descărcat în ~Library/Caches/org.swift.swiftpm/.
  5. Compilare — construiește toate țintele pachetului cu flag-urile proiectului principal.

Fișierul Package.resolved fixează versiunile exacte ale tuturor dependențelor, astfel încât echipa de dezvoltare să lucreze cu același set de biblioteci. Acest fișier trebuie adăugat în sistemul de control al versiunilor (git).

Avantajul cheie al SPM față de alternative — absența unui registru centralizat. Pachetele pot fi localizate în orice depozit Git public: GitHub, GitLab, Bitbucket, precum și pe serverele Git proprii ale companiei. Începând cu Swift 5.2, SPM suportă dependențe binare (binary targets) — biblioteci închise distribuite prin XCFramework fără a furniza codul sursă.

Package.swift — manifestul proiectului

Package.swift — este un fișier Swift care descrie structura pachetului și dependențele sale. Fișierul este scris în Swift însuși (nu JSON, nu YAML), ceea ce permite utilizarea logicii condiționale, constantelor calculate și funcțiilor în interiorul manifestului.

Structura de bază a 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"]
        ),
    ]
)

Să analizăm elementele cheie:

  • // swift-tools-version: 5.9 — directivă care indică versiunea SPM; de ea depinde sintaxa disponibilă a manifestului.
  • name — numele pachetului, afișat în Xcode și utilizat în referințele de dependențe.
  • platforms — versiunile minime ale platformelor; SPM nu va permite construirea pachetului pe o versiune mai veche de OS.
  • products — ceea ce „exportă" pachetul: bibliotecă (.library) sau fișier executabil (.executable).
  • dependencies — lista pachetelor externe cu URL și versiune; sunt suportate from:, exact:, branch:, revision:.
  • targets — ținte de compilare; fiecare țintă conține lista de dependențe, resurse și fișiere swift din directorul corespunzător (Sources/TargetName/).

Exemplu de specificare a versiunii exacte, ramurii și commit-ului:

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

Începând cu Swift 5.9, în Package.swift a fost adăugat suportul pentru static/framework și linkerSettings, ceea ce permite configurarea mai precisă a legăturii pentru bibliotecile statice și dinamice.

Comenzile principale SPM

Swift Package Manager oferă un set de comenzi pentru lucrul prin terminal. Comenzile se rulează din directorul rădăcină al pachetului (unde se află Package.swift).

bash
# Creează un pachet nou cu bibliotecă
swift package init --type library

# Creează un pachet executabil (aplicație consolă)
swift package init --type executable

# Construiește proiectul
swift build

# Construiește în configurația release
swift build -c release

# Rulează testele
swift test

# Rulează un test specific
swift test --filter "MyLibraryTests/testExample"

# Descarcă și rezolvă dependențele
swift package resolve

# Actualizează dependențele la cele mai recente versiuni disponibile
swift package update

# Arată graful de dependențe
swift package show-dependencies

# Curăță cache-ul de compilare
swift package clean

# Generează proiect Xcode (înainte de Xcode 11)
swift package generate-xcodeproj

În timpul lucrului în Xcode, majoritatea acestor comenzi se execută automat: dependențele sunt rezolvate la deschiderea proiectului, compilarea se rulează cu ⌘B, testele cu ⌘U. Cu toate acestea, cunoașterea comenzilor de terminal este necesară pentru pipeline-urile CI/CD (GitHub Actions, GitLab CI, Jenkins), unde Xcode nu este disponibil.

Comanda swift package resolve creează sau actualizează fișierul Package.resolved. Acest fișier fixează versiunile exacte ale tuturor dependențelor, inclusiv pe cele tranzitive, și trebuie adăugat în git. Se recomandă rularea swift package update înainte de fiecare ramură feature nouă, pentru a lucra cu versiunile actuale ale bibliotecilor.

Crearea propriului pachet

Crearea propriului pachet SPM este utilă pentru încapsularea logicii de business în proiecte multi-modul și pentru publicarea bibliotecilor open-source. Să analizăm procesul pas cu pas.

Pasul 1: Inițializare

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

Pasul 2: Structura directorului

Comanda swift package init creează următoarea structură:

text
MyNetworkKit/
├── Package.swift
├── README.md
├── Sources/
│   └── MyNetworkKit/
│       └── MyNetworkKit.swift
└── Tests/
    └── MyNetworkKitTests/
        └── MyNetworkKitTests.swift

SPM scanează automat directoarele Sources/ și Tests/: fiecare subdirector din Sources corespunde unei ținte (target).

Pasul 3: Editarea Package.swift

Adăugăm dependențe și configurăm platformele țintă:

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

Pasul 4: Scrierea codului

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

Pasul 5: Publicare

Împingeți pachetul în depozitul Git și creați un tag SemVer:

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

După aceasta, orice dezvoltator va putea conecta pachetul dvs. prin .package(url: "https://github.com/username/MyNetworkKit.git", from: "1.0.0").

Exemple de utilizare SPM

Exemplul 1: Conectarea Alamofire pentru cereri de rețea

Alamofire — cel mai popular client HTTP pentru Swift. Îl vom adăuga prin SPM și vom executa o cerere GET.

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("S-au primit \(users.count) utilizatori")
            case .failure(let error):
                print("Eroare: \(error.localizedDescription)")
            }
        }
}

Exemplul 2: Swinject — injectarea dependențelor

Biblioteca Swinject oferă un container DI pentru Swift. Se conectează prin .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()

Exemplul 3: Swift-log pentru logare structurată

Pachetul swift-log de la Apple — o API unificată de logare care suportă multiple backend-uri (OSLog, consolă, fișiere).

swift
import Logging

var logger = Logger(label: "com.myapp.network")
logger.logLevel = .debug

logger.info("Cerere de rețea începută", metadata: [
    "url": "\(requestURL)",
    "method": "GET"
])

logger.warning("Timpul de răspuns a depășit 2 secunde")
logger.error("Eroare de conexiune: fără internet")

Aceste trei exemple acoperă scenariile tipice de utilizare SPM: clienți HTTP, containere DI și infrastructură de sistem. Alegerea bibliotecilor nu este întâmplătoare — Alamofire, Swinject și swift-log se află în top 20 cele mai populare pachete Swift pe GitHub.

Migrarea de la CocoaPods și Carthage

Dacă proiectul utilizează CocoaPods sau Carthage, migrarea la SPM se face în câțiva pași. Procesul este sigur: dependențele SPM pot coexista cu CocoaPods și Carthage în același proiect, permițând migrarea treptată.

CocoaPods → SPM

  1. În Xcode: File → Add Package Dependency, introduceți URL-ul pachetului.
  2. Selectați versiunea și adăugați pachetul la targets-urile necesare.
  3. După adăugarea tuturor dependențelor prin SPM, ștergeți liniile din Podfile.
  4. Ștergeți .xcworkspace, deschideți .xcodeproj și executați Clean Build Folder.

Carthage → SPM

  1. Adăugați pachetele prin Xcode File → Add Package Dependency.
  2. Ștergeți dependențele din Cartfile.
  3. Ștergeți scripturile de construire Carthage din Build Phases.
  4. Curățați cache-ul: rm -rf Carthage/ în terminal.

În 2025, SPM suportă marea majoritate a bibliotecilor populare Swift. Excepțiile sunt unele framework-uri ObjC fără hărți de module (modulemap). Dacă o bibliotecă nu suportă încă SPM — verificați secțiunea Installation din README-ul său; majoritatea autorilor au adăugat deja suport SPM în cele mai recente versiuni.

Întrebări frecvente

Cu ce se deosebește SPM de CocoaPods și Carthage?

SPM este încorporat în compilatorul Swift și Xcode, nu necesită instalare prin gem sau Homebrew. CocoaPods utilizează un registru centralizat Specs și generează un workspace separat. Carthage funcționează prin framework-uri fără integrare în proiect. SPM este singurul manager integrat la nivel de compilator: dependențele sunt rezolvate, stocate în cache și construite în paralel cu codul principal.

Se poate folosi SPM pentru proiecte Objective-C?

Da, SPM suportă proiecte mixte Swift + Objective-C. Fișierele ObjC din cadrul pachetului SPM ajung automat în Umbrella Header cu condiția unui modulemap corect. Cu toate acestea, SPM nu suportă biblioteci statice ObjC care nu au o mapă de module. Se recomandă conectarea bibliotecilor ObjC prin SPM doar dacă acestea furnizează modulemap sau sunt scrise în C pur.

Cum rezolvă SPM conflictele de versiuni?

SPM utilizează versionarea semantică (SemVer). Dacă pachetul A necesită Alamofire 5.8+, iar pachetul B — Alamofire 5.9+, SPM va selecta versiunea 5.9.x care satisface ambele cerințe. Dacă conflictul este de nerezolvat (un pachet necesită 5.x, altul — 6.x), SPM va raporta o eroare. În acest caz, trebuie să actualizați unul dintre pachete sau să schimbați dependența la o versiune compatibilă cu ambele cerințe.

Unde sunt stocate pachetele SPM descărcate?

Pe macOS: ~Library/Caches/org.swift.swiftpm/ și ~/Library/Developer/Xcode/DerivedData/. Pe Linux: ~cache/swiftpm/. În timpul compilării, SPM stochează în cache codul sursă și fișierele obiect compilate. Pentru a curăța complet cache-ul, executați swift package reset — această comandă șterge cache-ul dependențelor și DerivedData pentru proiectul curent.

Suportă SPM biblioteci închise (proprietare)?

Da, începând cu Swift 5.2, SPM suportă ținte binare (binary targets). Biblioteca închisă este furnizată ca XCFramework, iar în Package.swift se indică calea către .xcframework. Codul sursă nu este dezvăluit. Binary target se specifică prin .binaryTarget(name: "PrivateSDK", path: "Sources/PrivateSDK.xcframework"). Acest lucru permite conectarea SDK-urilor comerciale fără a încălca acordurile de licență.

Concluzii

  • SPM (Swift Package Manager) — manager de pachete încorporat Swift care nu necesită instalare separată și este integrat cu Xcode și compilatorul.
  • Package.swift — manifest declarativ în limbajul Swift care descrie numele pachetului, platformele, dependențele, produsele și țintele de compilare.
  • SPM utilizează depozitele Git ca sursă de pachete și rezolvă versiunile conform SemVer, stocând în cache codul sursă pentru a accelera recompilările.
  • Comenzile principale: swift package init (creează pachet), swift build (construiește), swift test (testează), swift package update (actualizează dependențe).
  • Pachetul propriu se creează prin swift package init, se publică în Git și este disponibil altor proiecte prin URL cu tag SemVer.
  • Migrarea de la CocoaPods/Carthage la SPM este sigură: dependențele pot coexista, migrarea se face prin File → Add Package Dependency în Xcode.
  • SPM — standardul de gestionare a dependențelor în ecosistemul Swift, utilizat de 67% dintre dezvoltatorii iOS (Swift.org Developer Survey, 2024).

Vom dezvolta o aplicație mobilă la cheie

IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.

Discutați proiectul

Citiți și