Swift Package Manager у 2026: Створення, Публікація та Питання для Співбесід

Опануйте Swift Package Manager за допомогою цього детального посібника. Навчіться створювати пакети, керувати залежностями, публікувати бібліотеки та готуватися до питань iOS співбесід про SPM.

Swift Package Manager у 2026: Створення, Публікація та Питання для Співбесід

Swift Package Manager (SPM) відповідає за керування залежностями та розповсюдження пакетів у проєктах Swift. На відміну від CocoaPods чи Carthage, SPM інтегрований безпосередньо в Xcode та інструментарій Swift, не потребуючи зовнішнього встановлення. Swift 6.2 та 6.3 запровадили налаштування суворої безпеки памʼяті, ізоляцію акторів за замовчуванням та нову систему Swift Build, роблячи SPM безперечним вибором для сучасної iOS розробки.

Що робить SPM

Swift Package Manager розвʼязує залежності, завантажує вихідний код, компілює модулі та звʼязує їх у фінальний бінарний файл. Єдиний файл маніфесту Package.swift визначає все: залежності, цілі, продукти та налаштування збірки.

Структура та синтаксис маніфесту Package.swift

Кожен Swift пакет починається з файлу Package.swift у кореневій директорії репозиторію. Цей маніфест використовує код Swift для оголошення структури пакета, залежностей та конфігурації збірки.

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

Масив platforms визначає мінімальні версії розгортання. Секція products визначає, що можуть імпортувати інші пакети. Секція targets перелічує одиниці компіляції з їхніми відповідними залежностями.

Створення Swift пакету з командного рядка

Команда swift package init створює каркас нового пакета зі стандартною структурою директорій. Прапорець --type визначає, чи пакет створює бібліотеку чи виконуваний файл.

bash
# Створення пакету бібліотеки
mkdir NetworkKit && cd NetworkKit
swift package init --type=library

# Згенерована структура:
# NetworkKit/
# ├── Package.swift
# ├── Sources/
# │   └── NetworkKit/
# │       └── NetworkKit.swift
# └── Tests/
#     └── NetworkKitTests/
#         └── NetworkKitTests.swift

Виконання swift build компілює пакет. Виконання swift test запускає набір тестів. Обидві команди використовують конфігурацію з Package.swift без додаткового налаштування.

Вимоги до версій залежностей та їх розвʼязання

SPM підтримує три стратегії специфікації версій: точна версія, діапазон версій та посилання на гілку або коміт. Вибір впливає на відтворюваність та гнучкість.

Package.swiftswift
dependencies: [
    // Семантичне версіонування: від 5.9.0 до наступної мажорної версії
    .package(url: "https://github.com/Alamofire/Alamofire.git", from: "5.9.0"),
    
    // Точна версія: заблоковано на 5.9.1
    .package(url: "https://github.com/Alamofire/Alamofire.git", exact: "5.9.1"),
    
    // Діапазон версій: від 5.8.0 до 5.9.9
    .package(url: "https://github.com/Alamofire/Alamofire.git", "5.8.0".."5.9.9"),
    
    // Посилання на гілку: для розробки
    .package(url: "https://github.com/Alamofire/Alamofire.git", branch: "main"),
    
    // Посилання на коміт: прикріплено до конкретного коміту
    .package(url: "https://github.com/Alamofire/Alamofire.git", revision: "abc123")
]

Файл Package.resolved записує точні версії, визначені під час розвʼязання залежностей. Цей файл слід комітити до системи контролю версій для відтворюваних збірок серед членів команди та CI систем.

Залежності від гілок у продакшені

Посилання на гілки та коміти обходять семантичне версіонування. Використання branch: "main" у продакшен застосунку означає, що будь-який push до main може зламати збірку. Посилання на гілки слід залишати для активної розробки проти невипущених функцій.

Додавання пакетів до проєкту Xcode

Xcode інтегрує SPM через меню File. Перейдіть до File, потім Add Package Dependencies. Введіть URL репозиторію, виберіть правило версії та визначте, які цілі повинні підключати залежність.

AppDelegate.swiftswift
import UIKit
import Alamofire // Доступний після додавання через 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 зберігає посилання на пакети у файлі .xcodeproj, а розвʼязані версії в Package.resolved у корені проєкту. Папка Derived Data кешує завантажені пакети.

Розробка локальних пакетів із шляховими залежностями

Під час розробки вказівка на локальний шлях замість віддаленого URL дозволяє швидку ітерацію без публікації проміжних версій. Ця техніка підходить для конфігурацій монорепозиторію та розробки функцій.

Package.swift у споживаючому пакетіswift
dependencies: [
    // Локальний шлях для розробки
    .package(path: "../NetworkKit"),
    
    // Віддалений URL для релізу
    // .package(url: "https://github.com/company/NetworkKit.git", from: "1.0.0")
]

Перемикання між локальними та віддаленими залежностями здійснюється шляхом коментування неактивного рядка. Xcode та Swift CLI розвʼязують шляхові залежності відносно споживаючого пакету.

Готовий до співбесід з iOS?

Практикуйся з нашими інтерактивними симуляторами, flashcards та технічними тестами.

Публікація Swift пакету на GitHub

Публікація вимагає Git репозиторію з тегами семантичних версій. SPM розглядає теги Git як версії релізів. Swift Package Index автоматично індексує публічні пакети.

bash
# Ініціалізація репозиторію та 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

# Створення тегу версії
git tag 1.0.0
git push origin 1.0.0

# Інші пакети тепер можуть залежати від:
# .package(url: "https://github.com/username/NetworkKit.git", from: "1.0.0")

Дотримуйтесь конвенцій семантичного версіонування: збільшуйте мажорну версію для несумісних змін, мінорну для нових функцій і патч для виправлень помилок. SPM припускає дотримання цих правил при розвʼязанні вимог версії from:.

Налаштування пакетів у Swift 6.2 та 6.3

Swift 6.2 запровадив конфігурацію мовного режиму для окремих цілей та налаштування суворої безпеки памʼяті. Swift 6.3 додає інтеграцію Swift Build як опціональну систему збірки.

Package.swift з функціями 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: [
                // Увімкнення мовного режиму Swift 6 тільки для цієї цілі
                .swiftLanguageMode(.v6),
                // Увімкнення суворої перевірки безпеки памʼяті (SE-0458)
                .enableExperimentalFeature("StrictMemorySafety"),
                // Налаштування ізоляції акторів за замовчуванням (SE-0466)
                .enableExperimentalFeature("GlobalActorIsolation")
            ]
        )
    ]
)

Налаштування swiftLanguageMode дозволяє поступове впровадження функцій Swift 6 у кодовій базі. Цілі можуть використовувати різні мовні режими в межах одного пакета.

Генерація SBOM для відповідності вимогам безпеки

SE-0509 додав нативну генерацію Software Bill of Materials у Swift 6.3. Документи SBOM перелічують усі залежності та їхні версії для аудиту безпеки та регуляторної відповідності.

bash
# Генерація SBOM у форматі CycloneDX
swift build --sbom-spec cyclonedx

# Генерація SBOM за допомогою спеціальної підкоманди
swift package generate-sbom --format spdx

# Результат включає:
# - Назву та версію пакета
# - Усі транзитивні залежності
# - Інформацію про ліцензії
# - URL репозиторіїв-джерел

Корпоративні середовища та державні контракти все частіше вимагають документації SBOM. Формати CycloneDX та SPDX інтегруються зі стандартними інструментами сканування вразливостей.

Бінарні цілі та розповсюдження XCFramework

Бінарні цілі дозволяють розповсюджувати попередньо скомпільовані фреймворки замість вихідного коду. XCFramework обʼєднує бінарні файли для кількох платформ та архітектур.

Package.swift з бінарною ціллюswift
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..."
        )
    ]
)

// Генерація контрольної суми:
// swift package compute-checksum AnalyticsSDK-2.0.0.xcframework.zip

Бінарні цілі скорочують час збірки для споживачів та захищають пропрієтарні реалізації. Контрольна сума забезпечує цілісність завантаження.

Поширені питання співбесід про Swift Package Manager

Технічні співбесіди на iOS позиції часто включають питання про SPM. Діапазон охоплює від базового використання до архітектурних рішень.

П: Чим SPM відрізняється від CocoaPods та Carthage?

SPM інтегрується з Xcode та інструментарієм Swift без зовнішніх інструментів. CocoaPods використовує центральний репозиторій специфікацій та змінює структуру workspace Xcode. Carthage збирає фреймворки в окремому кроці без інтеграції з Xcode. SPM розвʼязує залежності та збирає в єдиному уніфікованому процесі. Документація Apple щодо Swift пакетів охоплює офіційні інструменти.

П: Що відбувається під час розвʼязання залежностей?

SPM рекурсивно читає маніфести Package.swift, будуючи граф залежностей. Потім застосовує обмеження версій, щоб знайти сумісні версії для всіх пакетів. Розвʼязувач записує точні версії до Package.resolved. Конфлікти виникають, коли два пакети вимагають несумісних версій спільної залежності.

П: Як розвʼязати конфлікт діамантової залежності?

Коли пакет A і B обидва залежать від пакета C з несумісними вимогами версій, SPM не може розвʼязати залежності. Рішення включають: оновлення одного споживача для підтримки ширшого діапазону версій, форк обмежувального пакета або використання псевдонімів модулів, якщо конфлікт між різними пакетами з однаковою назвою модуля.

swift
// Псевдоніми модулів для конфліктів назв
.target(
    name: "MyApp",
    dependencies: [
        .product(name: "Logging", package: "swift-log", moduleAliases: ["Logging": "SwiftLogging"])
    ]
)

П: Коли використовувати бінарну ціль замість розповсюдження вихідного коду?

Бінарні цілі підходять для пропрієтарних SDK, де розкриття коду неприпустиме, великих залежностей, де час компіляції впливає на продуктивність розробників, та попередньо скомпільованих бібліотек постачальників. Розповсюдження вихідного коду залишається переважним для проєктів з відкритим кодом та внутрішніх бібліотек, де налагодження в залежностях додає цінності.

Міграція з CocoaPods до Swift Package Manager

Міграція вимагає заміни записів Podfile посиланнями на пакети SPM. Не всі CocoaPods мають еквіваленти SPM, тому перед початком перевірте доступність на Swift Package Index.

ruby
# До: Podfile
pod 'Alamofire', '~> 5.9'
pod 'SwiftyJSON', '~> 5.0'
pod 'Kingfisher', '~> 7.0'
swift
// Після: Залежності пакетів у Xcode
// File > Add Package Dependencies для кожного:
// 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

Після міграції видаліть Podfile, Podfile.lock та директорію Pods. Виконання pod deintegrate видаляє модифікації workspace CocoaPods. Інструкції import у файлах Swift залишаються незмінними.

Найкращі практики SPM для продакшен застосунків

  • Закріплюйте мажорні версії за допомогою from: для стабільності, отримуючи мінорні оновлення та патчі
  • Комітьте Package.resolved для забезпечення відтворюваних збірок у команді
  • Використовуйте локальні пакети під час активної розробки, переключаючись на віддалені URL перед мерджем
  • Відокремлюйте залежності тільки для тестів за допомогою testTarget, щоб уникнути їх включення в релізні збірки
  • Документуйте мінімальну версію інструментів Swift на початку маніфесту: // swift-tools-version: 5.10
  • Перевіряйте збірки пакетів на CI перед тегуванням релізів
Версія інструментів Swift

Коментар // swift-tools-version: повинен зʼявитися у першому рядку Package.swift. Він визначає, яку версію API PackageDescription використовує маніфест. Swift 6.0 додав гнучкість, дозволяючи цьому коментарю бути в наступних рядках для заголовків ліцензій.

Ключові висновки для iOS розробників, що використовують SPM

  • SPM інтегрується нативно з Xcode, усуваючи накладні витрати на налаштування CocoaPods та Carthage
  • Маніфест Package.swift використовує код Swift, забезпечуючи типізовані оголошення залежностей
  • Вимоги версій підтримують діапазони семантичного версіонування, точні версії та посилання на гілки
  • Package.resolved блокує версії залежностей для відтворюваних збірок
  • Swift 6.2 додав мовні режими для окремих цілей та налаштування суворої безпеки памʼяті
  • Swift 6.3 запровадив генерацію SBOM для документації відповідності
  • Бінарні цілі розповсюджують попередньо скомпільовані XCFramework, коли розповсюдження вихідного коду непрактичне
  • Питання співбесід фокусуються на конфліктах розвʼязання, стратегіях міграції та архітектурних компромісах між SPM та альтернативами

Для комплексної підготовки до iOS співбесід перегляньте модулі керування станом SwiftUI та протоколо-орієнтоване програмування на SharpSkill.

Починай практикувати!

Перевір свої знання з нашими симуляторами співбесід та технічними тестами.

Щоденний виклик

Чи знайдеш ти помилку в iOS?

Справжній фрагмент коду, прихована помилка, одна спроба на день. Щоб спробувати, акаунт не потрібен.

Anthony Fillion-Maillet

Автор:

Anthony Fillion-Maillet

Засновник SharpSkill

Fullstack-розробник понад 10 років. Керує SharpSkill і відповідає за все, що тут публікується.

Оновлено 20 вересня 2026 р.

Поділитися

Пов'язані статті