Swift Package Manager w 2026: Tworzenie, Publikowanie i Pytania Rekrutacyjne

Opanuj Swift Package Manager dzięki temu kompleksowemu poradnikowi. Naucz się tworzyć pakiety, zarządzać zależnościami, publikować biblioteki i przygotuj się do pytań rekrutacyjnych iOS dotyczących SPM.

Swift Package Manager w 2026: Tworzenie, Publikowanie i Pytania Rekrutacyjne

Swift Package Manager (SPM) odpowiada za zarządzanie zależnościami i dystrybucję pakietów w projektach Swift. W przeciwieństwie do CocoaPods czy Carthage, SPM jest zintegrowany bezpośrednio z Xcode i toolchainem Swift, nie wymagając dodatkowej instalacji. Swift 6.2 i 6.3 wprowadzily ustawienia ścisłego bezpieczeństwa pamięci, domyślną izolację aktorów oraz nowy system Swift Build, czyniąc SPM definitywnym wyborem dla nowoczesnego rozwoju iOS.

Funkcje SPM

Swift Package Manager rozwiązuje zależności, pobiera kod źródłowy, kompiluje moduły i linkuje je do finalnego binarnego pliku. Pojedynczy plik manifestu Package.swift definiuje wszystko: zależności, cele, produkty i ustawienia budowania.

Struktura i składnia manifestu Package.swift

Każdy pakiet Swift zaczyna się od pliku Package.swift w katalogu głównym repozytorium. Ten manifest wykorzystuje kod Swift do deklarowania struktury pakietu, zależności i konfiguracji budowania.

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

Tablica platforms określa minimalne wersje docelowe wdrożenia. Sekcja products definiuje, co inne pakiety mogą importować. Sekcja targets wymienia jednostki kompilacji z ich odpowiednimi zależnościami.

Tworzenie pakietu Swift z wiersza poleceń

Polecenie swift package init tworzy szkielet nowego pakietu ze standardową strukturą katalogów. Flaga --type określa, czy pakiet produkuje bibliotekę czy plik wykonywalny.

bash
# Tworzenie pakietu biblioteki
mkdir NetworkKit && cd NetworkKit
swift package init --type=library

# Wygenerowana struktura:
# NetworkKit/
# ├── Package.swift
# ├── Sources/
# │   └── NetworkKit/
# │       └── NetworkKit.swift
# └── Tests/
#     └── NetworkKitTests/
#         └── NetworkKitTests.swift

Uruchomienie swift build kompiluje pakiet. Uruchomienie swift test wykonuje zestaw testów. Oba polecenia wykorzystują konfigurację z Package.swift bez dodatkowej konfiguracji.

Wymagania wersji zależności i ich rozwiązywanie

SPM obsługuje trzy strategie specyfikacji wersji: dokładna wersja, zakres wersji oraz odniesienie do gałęzi lub commita. Wybór wpływa na odtwarzalność i elastyczność.

Package.swiftswift
dependencies: [
    // Wersjonowanie semantyczne: od 5.9.0 do następnej głównej
    .package(url: "https://github.com/Alamofire/Alamofire.git", from: "5.9.0"),
    
    // Dokładna wersja: blokada na 5.9.1
    .package(url: "https://github.com/Alamofire/Alamofire.git", exact: "5.9.1"),
    
    // Zakres wersji: od 5.8.0 do 5.9.9
    .package(url: "https://github.com/Alamofire/Alamofire.git", "5.8.0".."5.9.9"),
    
    // Odniesienie do gałęzi: do rozwoju
    .package(url: "https://github.com/Alamofire/Alamofire.git", branch: "main"),
    
    // Odniesienie do commita: przypięty do konkretnego commita
    .package(url: "https://github.com/Alamofire/Alamofire.git", revision: "abc123")
]

Plik Package.resolved rejestruje dokładne wersje rozwiązane podczas rozwiązywania zależności. Ten plik powinien być dodany do kontroli wersji dla odtwarzalnych budowań wśród członków zespołu i systemów CI.

Zależności od gałęzi w produkcji

Odniesienia do gałęzi i commitów omijają wersjonowanie semantyczne. Użycie branch: "main" w aplikacji produkcyjnej oznacza, że każdy push do main może zepsuć budowanie. Odniesienia do gałęzi należy rezerwować dla aktywnego rozwoju przeciwko niewydanym funkcjom.

Dodawanie pakietów do projektu Xcode

Xcode integruje SPM poprzez menu File. Należy przejść do File, następnie Add Package Dependencies. Wprowadza się URL repozytorium, wybiera regułę wersji i określa, które cele powinny linkować zależność.

AppDelegate.swiftswift
import UIKit
import Alamofire // Dostępne po dodaniu przez 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 przechowuje odniesienia do pakietów w pliku .xcodeproj, a rozwiązane wersje w Package.resolved w katalogu głównym projektu. Folder Derived Data buforuje pobrane pakiety.

Rozwój lokalnych pakietów z zależnościami ścieżkowymi

Podczas rozwoju wskazanie na lokalną ścieżkę zamiast zdalnego URL umożliwia szybką iterację bez publikowania wersji pośrednich. Ta technika sprawdza się w konfiguracjach monorepo i podczas rozwoju funkcji.

Package.swift w pakiecie konsumującymswift
dependencies: [
    // Lokalna ścieżka do rozwoju
    .package(path: "../NetworkKit"),
    
    // Zdalny URL do wydania
    // .package(url: "https://github.com/company/NetworkKit.git", from: "1.0.0")
]

Przełączanie między lokalnymi a zdalnymi zależnościami odbywa się poprzez zakomentowanie nieaktywnej linii. Xcode i CLI Swift rozwiązują zależności ścieżkowe względem pakietu konsumującego.

Gotowy na rozmowy o iOS?

Ćwicz z naszymi interaktywnymi symulatorami, flashcards i testami technicznymi.

Publikowanie pakietu Swift na GitHub

Publikowanie wymaga repozytorium Git z tagami wersji semantycznych. SPM traktuje tagi Git jako wersje wydań. Swift Package Index automatycznie indeksuje pakiety publiczne.

bash
# Inicjalizacja repozytorium i push
git init
git add .
git commit -m "Initial commit"
git remote add origin https://github.com/username/NetworkKit.git
git push -u origin main

# Tworzenie tagu wersji
git tag 1.0.0
git push origin 1.0.0

# Inne pakiety mogą teraz zależeć od:
# .package(url: "https://github.com/username/NetworkKit.git", from: "1.0.0")

Należy przestrzegać konwencji wersjonowania semantycznego: zwiększać wersję główną dla zmian łamiących kompatybilność, mniejszą dla nowych funkcji i łatkę dla poprawek błędów. SPM zakłada przestrzeganie tych reguł przy rozwiązywaniu wymagań wersji from:.

Ustawienia pakietów w Swift 6.2 i 6.3

Swift 6.2 wprowadził konfigurację trybu językowego dla poszczególnych celów oraz ustawienia ścisłego bezpieczeństwa pamięci. Swift 6.3 dodaje integrację Swift Build jako opcjonalny system budowania.

Package.swift z funkcjami 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: [
                // Włączenie trybu językowego Swift 6 tylko dla tego celu
                .swiftLanguageMode(.v6),
                // Włączenie ścisłego sprawdzania bezpieczeństwa pamięci (SE-0458)
                .enableExperimentalFeature("StrictMemorySafety"),
                // Ustawienie domyślnej izolacji aktorów (SE-0466)
                .enableExperimentalFeature("GlobalActorIsolation")
            ]
        )
    ]
)

Ustawienie swiftLanguageMode pozwala na stopniowe przyjmowanie funkcji Swift 6 w całej bazie kodu. Cele mogą używać różnych trybów językowych w ramach tego samego pakietu.

Generowanie SBOM dla zgodności z bezpieczeństwem

SE-0509 dodało natywne generowanie Software Bill of Materials w Swift 6.3. Dokumenty SBOM wymieniają wszystkie zależności i ich wersje do audytu bezpieczeństwa i zgodności regulacyjnej.

bash
# Generowanie SBOM w formacie CycloneDX
swift build --sbom-spec cyclonedx

# Generowanie SBOM przy użyciu dedykowanej subkomendy
swift package generate-sbom --format spdx

# Wynik zawiera:
# - Nazwę i wersję pakietu
# - Wszystkie tranzytywne zależności
# - Informacje o licencjach
# - URL repozytoriów źródłowych

Środowiska korporacyjne i kontrakty rządowe coraz częściej wymagają dokumentacji SBOM. Formaty CycloneDX i SPDX integrują się ze standardowymi narzędziami do skanowania podatności.

Cele binarne i dystrybucja XCFramework

Cele binarne umożliwiają dystrybucję prekompilowanych frameworków zamiast kodu źródłowego. XCFrameworks łączą binarki dla wielu platform i architektur.

Package.swift z celem binarnymswift
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..."
        )
    ]
)

// Generowanie sumy kontrolnej:
// swift package compute-checksum AnalyticsSDK-2.0.0.xcframework.zip

Cele binarne skracają czas budowania dla konsumentów i chronią zastrzeżone implementacje. Suma kontrolna zapewnia integralność pobierania.

Typowe pytania rekrutacyjne dotyczące Swift Package Manager

Rozmowy techniczne na stanowiska iOS często zawierają pytania o SPM. Zakres obejmuje od podstawowego użycia po decyzje architektoniczne.

P: Czym SPM różni się od CocoaPods i Carthage?

SPM integruje się z Xcode i toolchainem Swift bez zewnętrznych narzędzi. CocoaPods używa centralnego repozytorium specyfikacji i modyfikuje strukturę workspace Xcode. Carthage buduje frameworki w osobnym kroku bez integracji z Xcode. SPM rozwiązuje zależności i buduje w jednym zunifikowanym procesie. Dokumentacja Apple dotycząca pakietów Swift obejmuje oficjalne narzędzia.

P: Co dzieje się podczas rozwiązywania zależności?

SPM rekurencyjnie odczytuje manifesty Package.swift, budując graf zależności. Następnie stosuje ograniczenia wersji, aby znaleźć kompatybilne wersje dla wszystkich pakietów. Resolver zapisuje dokładne wersje do Package.resolved. Konflikty występują, gdy dwa pakiety wymagają niekompatybilnych wersji wspólnej zależności.

P: Jak rozwiązać konflikt zależności diamentowej?

Gdy pakiet A i B oba zależą od pakietu C z niekompatybilnymi wymaganiami wersji, SPM nie może rozwiązać zależności. Rozwiązania obejmują: aktualizację jednego konsumenta do obsługi szerszego zakresu wersji, forkowanie restrykcyjnego pakietu lub użycie aliasów modułów, jeśli konflikt dotyczy różnych pakietów o tej samej nazwie modułu.

swift
// Aliasowanie modułów dla konfliktów nazw
.target(
    name: "MyApp",
    dependencies: [
        .product(name: "Logging", package: "swift-log", moduleAliases: ["Logging": "SwiftLogging"])
    ]
)

P: Kiedy używać celu binarnego zamiast dystrybucji źródłowej?

Cele binarne sprawdzają się w zastrzeżonych SDK, gdzie ekspozycja źródła jest niedopuszczalna, dużych zależnościach gdzie czas kompilacji wpływa na produktywność deweloperów oraz prekompilowanych bibliotekach dostawców. Dystrybucja źródłowa pozostaje preferowana dla projektów open source i wewnętrznych bibliotek, gdzie debugowanie w zależnościach dodaje wartość.

Migracja z CocoaPods do Swift Package Manager

Migracja wymaga zastąpienia wpisów Podfile odniesieniami do pakietów SPM. Nie wszystkie CocoaPods mają odpowiedniki SPM, więc przed rozpoczęciem należy zweryfikować dostępność na Swift Package Index.

ruby
# Przed: Podfile
pod 'Alamofire', '~> 5.9'
pod 'SwiftyJSON', '~> 5.0'
pod 'Kingfisher', '~> 7.0'
swift
// Po: Zależności pakietów w Xcode
// File > Add Package Dependencies dla każdego:
// 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

Po migracji należy usunąć Podfile, Podfile.lock i katalog Pods. Uruchomienie pod deintegrate usuwa modyfikacje workspace CocoaPods. Instrukcje import w plikach Swift pozostają niezmienione.

Najlepsze praktyki SPM dla aplikacji produkcyjnych

  • Przypinanie głównych wersji za pomocą from: dla stabilności przy jednoczesnym otrzymywaniu mniejszych aktualizacji i łatek
  • Commitowanie Package.resolved dla zapewnienia odtwarzalnych budowań w całym zespole
  • Używanie lokalnych pakietów podczas aktywnego rozwoju, przełączanie na zdalne URL przed mergowaniem
  • Separowanie zależności tylko do testów za pomocą testTarget, aby uniknąć ich dołączania do wydań
  • Dokumentowanie minimalnej wersji narzędzi Swift na górze manifestu: // swift-tools-version: 5.10
  • Walidowanie budowań pakietów na CI przed tagowaniem wydań
Wersja narzędzi Swift

Komentarz // swift-tools-version: musi pojawić się w pierwszej linii Package.swift. Określa on, której wersji API PackageDescription używa manifest. Swift 6.0 dodał elastyczność pozwalającą na umieszczenie tego komentarza w kolejnych liniach dla nagłówków licencji.

Kluczowe wnioski dla deweloperów iOS używających SPM

  • SPM integruje się natywnie z Xcode, eliminując narzut konfiguracji CocoaPods i Carthage
  • Manifest Package.swift używa kodu Swift, umożliwiając deklaracje zależności sprawdzane typowo
  • Wymagania wersji obsługują zakresy wersjonowania semantycznego, dokładne wersje i odniesienia do gałęzi
  • Package.resolved blokuje wersje zależności dla odtwarzalnych budowań
  • Swift 6.2 dodał tryby językowe dla poszczególnych celów i ustawienia ścisłego bezpieczeństwa pamięci
  • Swift 6.3 wprowadził generowanie SBOM dla dokumentacji zgodności
  • Cele binarne dystrybuują prekompilowane XCFrameworks, gdy dystrybucja źródłowa jest niepraktyczna
  • Pytania rekrutacyjne koncentrują się na konfliktach rozwiązywania, strategiach migracji i kompromisach architektonicznych między SPM a alternatywami

Dla kompleksowego przygotowania do rozmów iOS warto przejrzeć moduły zarządzanie stanem SwiftUI i programowanie zorientowane na protokoły na SharpSkill.

Zacznij ćwiczyć!

Sprawdź swoją wiedzę z naszymi symulatorami rozmów i testami technicznymi.

Wyzwanie dnia

Znajdziesz błąd w iOS?

Prawdziwy fragment kodu, ukryty błąd, jedna próba dziennie. Bez konta, żeby spróbować.

Anthony Fillion-Maillet

Autor:

Anthony Fillion-Maillet

Założyciel SharpSkill

Programista fullstack od ponad 10 lat. Prowadzi SharpSkill i odpowiada za wszystko, co się tu ukazuje.

Zaktualizowano 20 września 2026

Udostępnij

Powiązane artykuły