Swift Package Manager (SPM) — правильная модульная система для современного видеоприложения: видеочата, стриминга, записи или прямых трансляций. Он встроен в Xcode, нативно работает с границами конкурентности Swift 6 и в 2026 году остаётся единственным пакетным менеджером, который Apple рекомендует для нового кода под iOS. Сделано правильно — SPM удешевляет поддержку видеоприложения, ускоряет сборку и облегчает совместную работу команд над кодом. Сделано неправильно — превращается в ад из вложенных пакетов с пятнадцатиминутной разрешимостью зависимостей и хрупким CI.

Это руководство — плейбук, по которому Фора Софт выстраивает Swift Package Manager в видеоприложениях, действительно доходящих до продакшена: границы модулей, фиксация версий, Sendable-безопасные интерфейсы пакетов, выбор зависимостей для WebRTC и стриминга, CI-пайплайны и конкретная структура продакшен-уровневого Package.swift. Если вы создаёте приложение для видеоконференций, заменяете стриминговый стек или разрабатываете собственную обработку видео и аудио, именно эту модульную архитектуру стоит взять за основу.

Главное

SPM — выбор по умолчанию для новых iOS-видеоприложений. Встроен в Xcode, понимает Swift 6, удобен из командной строки и остаётся единственным менеджером, в котором границы Sendable аккуратно переносятся между модулями. CocoaPods актуален только для интеграции с легаси-кодом.

Делите по границам конкурентности, а не по фичам. Один SPM-модуль на каждую actor-зону (Signalling, MediaEngine, CaptureSession, MediaFX, UI) — это защищает от утечек Sendable между модулями.

Фиксируйте всё; обновляйте обдуманно. Держите Package.resolved в системе контроля версий, для ObjC-тяжёлых бинарей (WebRTC) пинуйте до точного коммита, а обновление зависимостей выносите в плановый ежеквартальный цикл, а не в случайные апдейты по дороге.

Бинарные таргеты ускоряют сборку WebRTC в десять раз. Распространяйте iOS-фреймворк Google WebRTC как бинарный .xcframework, а не из исходников. Чистая CI-сборка падает с десятков минут до меньше шестидесяти секунд.

Не дробите слишком сильно. Подпакеты повышают стоимость резолва и усложняют CI. Для видеоприложения сладкая точка обычно 6–10 модулей; всё, что больше 15, — как правило, признак случайной фрагментации.

Почему этот плейбук написала Фора Софт

Фора Софт выпускает видео- и аудио-приложения для iOS с 2005 года — этого срока достаточно, чтобы помнить CocoaPods, Carthage и все три итерации SPM до того, как он стал зрелым. Мы используем SPM в продакшене в обучающей платформе BrainCert, корпоративном видеоинструменте VALT для проверки записей, видеоэффектах SuperPower FX и приложениях-компаньонах для Smart TV в проекте bellicon.

Этот плейбук — модульная архитектура, которую мы применяем ежедневно, отточенная на миграциях с CocoaPods на SPM, со Swift 5 на Swift 6 и с одномодульных монолитов на правильно нарезанные пакеты. Подход Agent Engineering (старшие инженеры, контролирующие Cursor/Claude/Copilot) удерживает рефакторинг под SPM в рамках бюджета и обычно даёт 20–40% экономии относительно стандартных ставок агентств, потому что AI-напарник особенно хорош в механических задачах модульной миграции.

Запутались в настройке Swift Package Manager?

Медленные сборки, ад зависимостей, утечки Sendable между модулями? Пришлите нам ваш Package.swift и примерный список модулей. Мы вернёмся с чистой схемой раскладки и точной оценкой.

Позвоните нам → Напишите нам →

SPM, CocoaPods и Carthage — что выбрать в 2026 году

Для нового видеоприложения единственный осмысленный выбор — SPM. Для легаси-приложения миграцию с CocoaPods стоит запланировать, но не торопиться: CocoaPods на момент публикации всё ещё работает и поддерживается.

Параметр SPM CocoaPods Carthage
Интеграция с Xcode Нативная Через плагин Вручную
Конкурентность Swift 6 Модульные swiftSettings Только обходные пути Только обходные пути
Бинарные таргеты XCFramework Подключаемый бинарь Да
Производительность CI Хорошая (с кэшем) Неровная Быстрая для собранных артефактов
Приватные репозитории Нативно SSH / HTTPS Приватный specs-репозиторий Git-URL
По умолчанию для нового iOS-приложения Да Только легаси Редко

Берите SPM, когда: начинаете новый iOS-проект, мигрируете легаси-приложение на Swift 6 или сводите управление зависимостями в нескольких командах. Серьёзных причин выбирать CocoaPods для нового проекта не осталось.

Раскладка модулей для продакшен-видеоприложения

Ниже — структура, которую мы выпускаем для видеочата или стриминг-приложения на Swift 6. Каждый модуль закреплён за своей зоной конкурентности, минимизирует публичную поверхность и делает границы Sendable проверяемыми на этапе компиляции.

MyVideoApp/
  Package.swift
  Sources/
    Core/              // Sendable types, errors, logging (zero deps)
    Signalling/        // WebSocket + protocol (depends: Core)
    Networking/        // REST / auth (depends: Core)
    MediaEngine/       // WebRTC wrapper actor (depends: Core, WebRTCBinary)
    CaptureSession/    // AVCaptureSession actor (depends: Core)
    MediaFX/           // Core ML, filters (depends: Core)
    CallFlow/          // orchestration actor (depends: all above)
    UIKitVideoView/    // UIViewRepresentable + Metal (depends: Core)
    Features/          // SwiftUI feature slices (depends: CallFlow, UIKitVideoView)
  BinaryFrameworks/
    WebRTC.xcframework
  Tests/
    ...
App/                   // the Xcode project (depends on Features)

Xcode-проект уровня приложения зависит только от Features; ничему в UI или связующем коде не нужно знать о WebRTC или Core ML. Бинарные таргеты (WebRTC) лежат за пределами Sources/ и подключаются из манифеста пакета.

Базовый Package.swift

Ниже — каркас манифеста, с которого мы начинаем. Swift-tools 6.0, индивидуальные swiftSettings на модуль, явный бинарный таргет и сквозная проверка Sendable.

// swift-tools-version: 6.0
import PackageDescription

let swift6Settings: [SwiftSetting] = [
  .enableExperimentalFeature("StrictConcurrency"),
  .enableUpcomingFeature("InferSendableFromCaptures"),
]

let package = Package(
  name: "MyVideoApp",
  platforms: [.iOS(.v17)],
  products: [
    .library(name: "Features", targets: ["Features"]),
  ],
  dependencies: [
    .package(url: "https://github.com/google/GoogleWebRTC", exact: "125.6422.06"),
    // pin every external dep to `exact` in production
  ],
  targets: [
    .binaryTarget(
      name: "WebRTC",
      path: "BinaryFrameworks/WebRTC.xcframework"
    ),
    .target(name: "Core", swiftSettings: swift6Settings),
    .target(
      name: "MediaEngine",
      dependencies: ["Core", "WebRTC"],
      swiftSettings: swift6Settings
    ),
    // ...repeat per module
    .testTarget(
      name: "MediaEngineTests",
      dependencies: ["MediaEngine"],
      swiftSettings: swift6Settings
    ),
  ]
)

Берите бинарные таргеты, когда: зависимость медленно собирается из исходников (WebRTC, FFmpeg, TensorFlow Lite), распространяется как закрытый бинарь или редко меняется. Всё остальное компилируйте из исходников — так стектрейсы и отладка остаются чистыми.

Sendable-безопасные интерфейсы модулей

Чистота Sendable между модулями — то, что отличает быструю сборку Swift 6 от запутанной. Интерфейсы остаются опрятными при соблюдении трёх правил:

1. Публичные типы — только в Core. Модуль Core владеет всеми Sendable-типами-значениями, которые расшариваются между модулями: ID, ошибки, статистики, снапшоты состояния. Никакой другой модуль не экспортирует Sendable-типы.

2. API actor’ов возвращают Sendable-значения. Когда MediaEngine передаёт состояние UI-слою, он возвращает снапшоты Core.CallState, а не внутренний RTCPeerConnection.

3. sending-параметры через границы модулей. Буферы, payload’ы и одноразовые объекты передаются как sending. Вызывающая сторона документирует передачу владения; компилятор её обеспечивает.

Каталог SPM-зависимостей для видеоприложений

За десять лет работы над видеоприложениями мы пришли к короткому списку зависимостей, которым доверяем в 2026 году. Несколько грамотно выбранных пакетов лучше длинного Package.resolved.

1. Google WebRTC. Бинарный XCFramework. Пинуйте к точному upstream-тегу. Обновляйте ежеквартально.

2. Альтернативы WebRTC под Apple. LiveKit Swift SDK — если используете LiveKit Cloud или self-hosted LiveKit SFU; команда сопровождает первоклассный SPM-таргет.

3. Starscream или URLSessionWebSocketTask. WebSocket-клиент для сигналинга. Starscream обкатан годами; URLSession не приносит лишних зависимостей и подходит, если расширения вам не нужны.

4. Swift Collections и Swift Algorithms. Околостандартные коллекции (OrderedSet, Deque) и ленивые алгоритмы. Нулевой риск.

5. swift-log. Структурированное логирование со сменными бэкендами. Одна строка — и вы переключаетесь с консольных логов в разработке на OSLog или удалённый бэкенд в продакшене.

6. Kingfisher или SDWebImage. Только если нужно агрессивное кэширование изображений (аватары на масштабе). Для простых случаев хватает AsyncImage и небольшого собственного кэша.

7. Core ML + Vision (без зависимостей). Весь on-device AI в 2026 году решается фреймворками Apple; стороння обёртка не даёт достаточно ценности, чтобы оправдать риск.

Нужна помощь, чтобы подчистить Package.resolved?

Мы регулярно сокращаем дерево SPM-зависимостей в продакшен-видеоприложениях на 30–60% без потери функциональности. Пришлите ваш манифест — мы вернёмся со списком на удаление и оценкой выигрыша по времени сборки.

Позвоните нам → Напишите нам →

CI и кэширование сборки — что реально ускоряет билды

Время CI у видеоприложения на SPM определяют три рычага:

1. Бинарный WebRTC. Поставка WebRTC как XCFramework сокращает чистую сборку с 15–25 минут (из исходников) до менее минуты (бинарь). Это самая мощная разовая оптимизация CI.

2. Кэш SPM в CI. Кэшируйте каталог .build и ~/Library/Caches/org.swift.swiftpm на CI-раннере. GitHub Actions, Bitrise и Xcode Cloud поддерживают это конфигом менее чем на 15 строк.

3. Инкрементальные сборки и Explicit Module Builds. Xcode 15+ умеет в явные модульные сборки. На крупных кодовых базах они радикально ускоряют инкрементальные билды; включайте на таргете.

В сумме грамотно настроенный CI-пайплайн для среднего видеоприложения укладывается в «тест + архив» за 10 минут — этого достаточно для нескольких релизов в день, к которым стремятся современные продуктовые команды.

Версионирование, пиннинг и квартальное обновление зависимостей

В продакшен-видеоприложениях мы пиним каждую внешнюю зависимость к точной версии, коммитим Package.resolved и обновляем зависимости по ежеквартальному графику, а не случайными PR’ами. Исключение — патчи безопасности; они идут вне очереди.

Для бинарей (WebRTC, FFmpeg, модели Core ML) пиним к точному SHA архива .xcframework. Расхождение бинарей — это самый неприятный класс продакшен-багов, потому что они тихо пересобираются на новом CI-раннере, и тесты не успевают поймать изменение.

Берите пиннинг к точной версии, когда: зависимость — часть рабочего продакшен-пайплайна. Ослабляйте до .upToNextMinor только для внутренних чисто-Swift утилит, где ломающие изменения редки и малозначимы.

Тестирование видеоприложения на Swift Package Manager

Нативный testTarget в SPM аккуратно сочетается со Swift Testing. Тест-таргет на модуль, @Suite на каждый ключевой сценарий, параметризованные тесты для матричного покрытия.

Интеграционные и UI-тесты держите на уровне Xcode-проекта (XCUITest), а не внутри SPM: тесты SPM по умолчанию всё ещё запускаются без устройства и не подходят для покрытия взаимодействий UIKit/SwiftUI. Наш общий подход к QA описан в отдельной статье о процессе тестирования в Фора Софт.

Миграция с CocoaPods на SPM без поломки сборки

Безопасный путь миграции — в три фазы:

Фаза 1 — двойной резолв. Оставляем Podfile. Добавляем Package.swift с первым модулем (обычно Core). Убеждаемся, что Xcode и CI собирают оба резолвера чисто.

Фаза 2 — переносим зависимости по одной. Каждый CocoaPod уезжает в SPM за один релиз-цикл, в первую очередь — чисто-Swift зависимости. Objective-C-зависимости (WebRTC, помощники для AVFoundation) обычно требуют упаковки в XCFramework; их планируйте последними.

Фаза 3 — удаляем Podfile. Только после того, как последний под исчез и полноценный релиз ушёл в стор уже исключительно под SPM. Не торопитесь: живой откат на CocoaPods во время миграции — дешёвая страховка.

Безопасность, цепочка поставок и пакеты, которые вы реально проверяете

Каждая зависимость в SPM — это код, который вы поставляете пользователю. Для видеоприложения, работающего со сквозным шифрованием, пользовательским медиа или контентом под HIPAA, относитесь к дереву зависимостей как к активу безопасности.

1. Проверяйте каждую зависимость перед подключением. Лицензия, мейнтейнер, дата последнего коммита, открытые предупреждения по безопасности. Если хотя бы один пункт срабатывает — ищите альтернативу или вендорьте только нужный кусок кода.

2. Подписывайте и проверяйте бинарные таргеты. SPM умеет работать с подписанными чексуммами XCFramework — используйте их для каждой бинарной зависимости. Тихая подмена бинаря на вашем хостинге — это атака на цепочку поставок.

3. Следите за CVE. Подпишитесь на CVE-фид по каждой зависимости или автоматизируйте через Dependabot / Renovate, которые открывают PR против вашего Package.swift.

Берите внутренний вендоринг зависимости, когда: upstream заброшен, критический CVE не закрыт или ваш скоуп соответствия (HIPAA, SOC 2) требует аудируемого форка, который вы контролируете сами.

Экономика — бюджеты рефакторинга под SPM

Ориентировочные цифры для продакшен-видеоприложений, по размеру кодовой базы. Конкретика меняется в зависимости от количества зависимостей и объёма Objective-C-моста.

1. Небольшое iOS-видеоприложение (<50 тыс. строк, 5–8 зависимостей). Миграция CocoaPods → SPM: 1–2 инженеро-недели. Разделение на модули: ещё 1–2.

2. Среднее приложение (50–200 тыс. строк, 10–20 зависимостей). Миграция: 3–5 недель. Полное разделение по зонам конкурентности: ещё 4–6 недель.

3. Крупное приложение (200 тыс.+ строк, 25+ зависимостей, тяжёлый ObjC). Миграция: 8–12 недель и два релиза. Модульная работа — отдельный подпроект (12–20 недель), обычно совпадающий с миграцией на Swift 6.

4. Упаковка бинарного таргета для внутреннего SDK. 1–2 недели на SDK для первичного XCFramework и пайплайна релиза. Дальше квартальные обновления укладываются в один рабочий день.

Agent Engineering сокращает каждую из этих оценок на 20–40% при чётко описанной миграции. За честной оценкой именно по вашему репозиторию — позвоните или напишите нам.

Мини-кейс — рефакторинг под SPM в корпоративном видеоприложении

Ситуация. Корпоративное видеоприложение с 20+ подами в CocoaPods, монолит на один модуль, 20-минутная чистая CI-сборка и нарастающая боль миграции на Swift 6. Цель: жить в SPM, разнести модули по зонам конкурентности, уложить чистый CI меньше чем в 10 минут и не сорвать релизный ритм.

План на 12 недель. Недели 1–3: каркас Package.swift, выделение модуля Core, двойной резолв вместе с существующим Podfile. Недели 4–7: миграция чисто-Swift подов по релизам (перенесено 7 зависимостей). Недели 8–9: WebRTC переупакован в XCFramework; выделены MediaEngine, CaptureSession и Signalling. Недели 10–11: Podfile удалён, CI-кэш донастроен, конкурентность Swift 6 включена помодульно. Неделя 12: выкатка и ретро.

Итог. Чистая CI-сборка сократилась с ~20 минут до менее 8. Новые границы модулей при переходе на Swift 6 поймали три скрытые проблемы конкурентности, которые до этого тихо уезжали в релизы. Скорость работы над фичами выросла: параллельная работа над MediaEngine и Features перестала упираться сама в себя.

Фреймворк принятия решения — спланируйте свой SPM за пять вопросов

1. Greenfield или легаси? Greenfield — SPM с первого дня. Легаси — планируйте миграцию на два-три релиза, а не одним большим спринтом.

2. Swift 6 или ещё Swift 5? SPM-модули по зонам конкурентности максимально окупаются на Swift 6. Если вы уже на Swift 5.10 с полной проверкой, основной выигрыш у вас тоже есть.

3. WebRTC бинарём или из исходников? Бинарь — ради скорости CI; исходники — только если нужен собственный патч или вы сидите на не-LTS-ветке WebRTC.

4. Зависимость открытая или приватная? Открытые подключаются в основной Package.swift. Приватные живут в отдельном приватном репозитории с настроенным SSH-доступом в CI.

5. Кто отвечает за апгрейды зависимостей? Назначайте каждый квартал одного инженера на роль «уборщика зависимостей»: разобрать накопленные обновления, прочитать changelog, провести апгрейд через PR. Ротация — раз в квартал.

Грабли, которых стоит избегать

1. Один модуль на каждую фичу. Модули по фичам выглядят аккуратно, но обычно дают циклические графы зависимостей. Делите по зонам конкурентности или архитектурным слоям; фичи — это каталоги внутри этих модулей.

2. Сборка WebRTC из исходников в CI. Если только вам не нужна собственная ветка, используйте бинарный XCFramework. Ежедневный выигрыш в CI огромен.

3. .upToNextMajor на всё подряд. Открытые диапазоны версий в продакшене гарантируют сюрприз посреди релиза. Фиксируйте точно; обновляйте осознанно.

4. Постоянное сосуществование SPM и CocoaPods. Двойной резолв нормален во время миграции. Если через год вы всё ещё запускаете оба — Podfile тихо превратился в кладбище зависимостей.

5. Игнор кэша пакетов в CI. Без кэша каждый PR пересобирает каждую зависимость с нуля. Пятнадцать строк CI-конфига — самая дешёвая оптимизация в стеке.

KPI — что измерять после рефакторинга под SPM

KPI качества. Количество вхождений @unchecked Sendable (чем меньше, тем лучше), межмодульные предупреждения Swift 6 в CI (цель — ноль) и число зависимостей на критическом пути.

Бизнес-KPI. Время цикла фичи до и после разделения модулей, задержка от «CI зелёный» до деплоя и время онбординга новых инженеров (должно падать по мере того, как граф модулей становится читаемым).

KPI надёжности. Время чистой CI-сборки, время инкрементальной CI-сборки и частота сообщений «почему у меня упал билд» в чате. Все три показателя должны заметно снизиться после правильно настроенного SPM.

Когда не стоит затевать SPM-рефакторинг в этом квартале

SPM — правильный пункт назначения для большинства iOS-видеоприложений, но не всегда уже в этом квартале. Отложите, если команда посреди миграции на Swift 6 или SwiftUI (одну миграцию за раз), если продукт находится в окне фризинга ради комплаенса или ревью App Store, либо если релизный ритм и так под давлением, а CI едва зелёный.

В этих случаях планируйте рефакторинг под SPM как первый проект следующего квартала. Он окупается быстрее всего, когда вы стартуете со стабильной базы, а не посреди другой миграции.

Готовы перестроить видеоприложение вокруг Swift Package Manager?

Мы переводили продакшен-iOS-видеоприложения с CocoaPods-монолитов на структуру Swift 6 + SPM. Пришлите репозиторий и целевой релиз — вернёмся с поэтапным планом.

Позвоните нам → Напишите нам →

FAQ

Готов ли Swift Package Manager для продакшен-видеоприложений?

Да. SPM встроен в Xcode начиная с Xcode 11, стабилен под Swift 5+, а в Swift 6 это единственный менеджер, который отслеживает границы конкурентности на уровне модулей. Мы используем его в продакшене в нескольких выпущенных видеоприложениях.

Сколько модулей — это уже слишком много?

Для типичного видеоприложения золотая середина — 6–10 модулей. После 15 обычно начинается убывающая отдача и растущие накладные расходы CI. Делите по зонам конкурентности или архитектурным слоям, а не по фичам.

Может ли SPM заменить CocoaPods для легаси-кода на Objective-C?

Да, но работы заметно больше. Objective-C-зависимости требуют упаковки в XCFramework или аккуратной работы с module-map. Если ObjC много, планируйте миграцию на два-три релиза, а не один спринт.

Как управлять приватными SPM-пакетами?

Храните их в приватном Git-репозитории, подключайтесь по SSH или HTTPS с токеном, настройте CI-учётки. Никакого центрального реестра не требуется. Для крупных организаций отдельный репозиторий «общих пакетов» помогает находить внутренние SDK, не засоряя Package.swift каждого приложения.

Нужно ли самим собирать бинарь Google WebRTC?

Google публикует официальный XCFramework. Заведите его зеркало в своём хранилище (S3 или GCS) и подключайте именно этот URL из Package.swift — так ваша сборка не зависит от изменений upstream. Пиньте всегда к точному SHA.

Как SPM влияет на время сборки больших видеоприложений?

С бинарным WebRTC, CI-кэшем и явными модульными сборками среднее видеоприложение обычно делает чистую сборку меньше чем за 10 минут, а инкрементальную PR-сборку — меньше чем за 3. Монолитный Xcode-проект с CocoaPods обычно превышает эти цифры в 2–3 раза.

Как выглядит SPM-проект с Фора Софт?

Обычно 2–3 недели discovery: аудит репозитория, предложенная раскладка модулей, выбор порядка миграции. Дальше — выделенная спринт-команда выпускает рефакторинг в течение двух-трёх ваших обычных релизных циклов. Часто работаем с клиентами как выделенная команда разработки.

Подходит ли SPM для Smart TV и tvOS-видеоприложений?

Да. Таргеты SPM поддерживают tvOS как платформу, и та же раскладка модулей переносится с iOS на tvOS с минимальными правками (ввод, focus engine). Мы используем такой подход в продакшене на Smart TV-приложениях — например, в проекте bellicon Smart TV.

Язык

Swift 6: что важно знать

Языковой партнёр SPM — конкурентность, Sendable, sending, типизированные throws.

Видео

Swift 6 для разработки видеочата на iOS

Прикладной взгляд на SPM + Swift 6 для iOS-видеочата.

UI

SwiftUI vs UIKit для видеоконференций

Где SwiftUI выигрывает, а где UIKit ещё оправдывает место в видеоприложении.

Интероп

Интеграция SIP в видеоконференцсвязь

Когда PSTN и легаси SIP-эндпоинты встречают вашу современную SFU на SPM.

Контекст

Технический дайджест лета 2025

iOS 26, Swift на Android, GPT-5 — релизный контекст вокруг Swift 6 и SPM.

Готовы заставить Swift Package Manager работать на ваше видеоприложение?

SPM — модульная система по умолчанию для современной iOS-видеоразработки: встроена в Xcode, понимает Swift 6, дружит с CI и остаётся единственным менеджером, где границы конкурентности чисто переносятся между модулями. Делите по зонам конкурентности, фиксируйте зависимости точно, поставляйте WebRTC бинарём, кэшируйте CI — и на выходе получаете проект, который быстро компилируется, легко читается на ревью и масштабируется на нескольких команд.

Если вы прорабатываете новое видеоприложение или мигрируете монолит на CocoaPods к SPM + Swift 6, плейбук выше — тот самый, по которому мы работаем каждый день. Когда понадобятся инженеры, которые уже выпускали такую структуру в продакшен, мы — на расстоянии одного звонка или письма.

Хотите применить SPM-плейбук к вашему репозиторию?

Напишите нам, сколько у вас зависимостей, какое время CI и в каком статусе Swift 6. Мы вернёмся с поэтапным планом рефакторинга и обоснованной оценкой.

Позвоните нам → Напишите нам →

  • Технологии