Scheme в Xcode — это конфигурация, которая определяет, как собирать, тестировать, профилировать и архивировать приложение для iOS, macOS, watchOS или tvOS. Каждая Scheme содержит набор действий (Build, Run, Test, Profile, Analyze, Archive) с собственными параметрами, аргументами и переменными окружения. По данным Apple Developer Documentation, 2025, Scheme является основным инструментом управления сборочными конфигурациями в Xcode, заменяя ручное переключение параметров. Xcode автоматически создаёт схему для каждого таргета при первом открытии проекта.
Главное
Scheme в Xcode — это XML-файл (расширение .xcscheme), который описывает последовательность действий и их параметры для сборки и анализа приложения. Каждый Scheme привязан к одному или нескольким таргетам и определяет, с какой конфигурацией (Debug, Release, AdHoc) выполнять каждое действие. Scheme — аналог Build Variant в Android, но с более гибкой структурой: одна схема может содержать разные таргеты для разных действий.
Xcode автоматически создаёт схему для каждого таргета при первом открытии проекта. Имя схемы по умолчанию совпадает с именем таргета. Если в проекте есть тестовый таргет, Xcode автоматически добавляет его в Test action схемы основного таргета. Для проектов с несколькими таргетами (основное приложение + watchOS + extension) Xcode создаёт отдельную схему для каждого, но можно создать одну схему, которая собирает все таргеты сразу.
Scheme хранятся в директории xcshareddata/xcschemes/ (для shared) или xcuserdata/<user>/xcschemes/ (для private). Shared схемы попадают в Git и используются всей командой. Private схемы хранятся локально и не синхронизируются. Файл .xcscheme имеет XML-формат с корневым элементом <Scheme>. Внутри — блоки для каждого действия: BuildAction, TestAction, LaunchAction, ProfileAction, AnalyzeAction, ArchiveAction.
.xcscheme — это XML-файл, который можно редактировать вручную или через Xcode. Основные элементы: <BuildAction> (список собираемых таргетов), <TestAction> (ссылки на тестовые таргеты), <LaunchAction> (конфигурация запуска), <ProfileAction>, <AnalyzeAction>, <ArchiveAction>. Каждый блок содержит атрибут buildConfiguration, который определяет, какую конфигурацию (Debug/Release) использовать для данного действия.
Scheme состоит из шести действий, каждое из которых можно настроить независимо. Build Action определяет, какие таргеты собираются и в каком порядке. Run Action — как запускается приложение: с какими аргументами, переменными окружения и какой конфигурацией. Test Action — какие тесты выполняются и какие code coverage опции включены. Profile Action — запуск с инструментами Instruments для профилирования. Analyze Action — статический анализ кода с Clang Static Analyzer. Archive Action — сборка для публикации в App Store или AdHoc-распространения.
Для каждого действия можно задать отдельную build configuration. Обычно для Run и Test используется Debug, для Archive — Release. Build configuration определяет набор флагов компилятора, оптимизации и отладочной информации. Xcode предоставляет две стандартные конфигурации: Debug (без оптимизаций, с символами отладки) и Release (с оптимизациями, без отладочной информации). Разработчик может добавлять кастомные конфигурации через проект.xcconfig.
Action Archive особенно важен — он создаёт .xcarchive, который затем экспортируется в .ipa для App Store или AdHoc. Archive Action использует Release-конфигурацию по умолчанию, но можно переключить на AdHoc или Distribution. В Archive Action также доступен флаг revealArchiveInOrganizer — после завершения архивирования Xcode открывает Organiser для дальнейших действий с архивом.
<!-- Пример .xcscheme для iOS приложения -->
<Scheme
LastUpgradeVersion = "1500"
version = "1.7">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "ABCD1234"
BuildableName = "MyApp.app"
BlueprintName = "MyApp"
ReferencedContainer = "container:MyApp.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
enableAddressSanitizer = "YES">
</LaunchAction>
</Scheme>
Создание новой схемы выполняется через меню Xcode: Product → Scheme → New Scheme или кнопкой "+" в панели Scheme (рядом с кнопкой Run). При создании выбирается таргет, для которого создаётся схема. Xcode автоматически копирует настройки из существующей схемы, если она выбрана как "duplicate". Новые схемы по умолчанию сохраняются как private — для публикации команде нужно включить Shared в Manage Schemes.
Окно Edit Scheme (Product → Scheme → Edit Scheme) содержит шесть вкладок по числу действий. На каждой вкладке можно изменить build configuration, аргументы запуска, переменные окружения, диагностические флаги. На вкладке Run доступны опции: executable (какой бинарник запускать), wait for executable to be launched (для отладки запускаемых процессов), debugger (LLDB или None), launch arguments, environment variables, и расширенные опции (Address Sanitizer, Thread Sanitizer, Main Thread Checker, Memory Management).
Для диагностики Address Sanitizer (ASan) — детектирует выход за границы массива, use-after-free и другие ошибки памяти в C/C++/ObjC коде. Thread Sanitizer (TSan) — детектирует состояния гонки (data races) в многопоточном коде. Undefined Behavior Sanitizer (UBSan) — выявляет неопределённое поведение, например переполнение знакового int. Эти опции доступны в Edit Scheme → Run → Diagnostics и работают только для Debug-сборок. Включение всех сanitizer'ов может замедлить запуск в 2-3 раза, поэтому рекомендуется включать их выборочно.
Типичная практика — создавать отдельные схемы для каждой среды окружения: Dev, Staging, Production. Каждая схема использует одни и те же Build Configuration (Debug для Dev, Release для Production), но разные аргументы запуска: -FIRAnalyticsDebugEnabled, -com.apple.CoreData.SQLDebug 1 для Dev, и их отсутствие для Production. Аргументы запуска передаются в UserDefaults (ProcessInfo.processInfo.arguments) и доступны для чтения на старте приложения. Это позволяет переключать URL сервера, уровень логирования и фичи без изменения кода.
Shared схемы хранятся в <project>.xcworkspace/xcshareddata/xcschemes/ или <project>.xcodeproj/xcshareddata/xcschemes/ и попадают в репозиторий Git. Все разработчики команды видят эти схемы в Xcode. Shared схемы — единственный способ распространять схемы в команде. Если разработчик создал важную схему (например, "Staging Archive"), но не отметил её как Shared, остальная команда её не увидит, что приводит к путанице: каждый будет создавать свою схему со своими настройками.
Private схемы хранятся в xcuserdata/<user>/xcschemes/ и не попадают в Git. Они полезны для персональных конфигураций: например, схема с включёнными всеми сanitizer'ами для конкретного разработчика. Private схемы не должны содержать критических настроек, от которых зависит сборка проекта — если разработчик уволит проект, его private схемы пропадут. Рекомендуется: все схемы, используемые в CI/CD и хотя бы двумя разработчиками, делать Shared.
Управление схемами выполняется через Manage Schemes (Product → Scheme → Manage Schemes). В окне отображаются все схемы проекта, их статус (Shared/Private), и кнопки +/— для добавления/удаления. Флажок Shared переключает видимость схемы для команды. При конфликте Git (изменения в .xcscheme от двух разработчиков) нужно аккуратно разрешать слияние — XML-файлы могут содержать разные идентификаторы таргетов. Рекомендуется добавлять .xcscheme в файлы, блокируемые при merge (git lfs или .gitattributes).
Arguments в Scheme — это строки, которые передаются приложению при запуске (ProcessInfo.processInfo.arguments) и переменные окружения (ProcessInfo.processInfo.environment). Аргументы используются для флагов: -AppleLanguages (ru), -AppleLocale ru_RU для симуляции русской локали, или -FIRDebugEnabled для включения отладки Firebase. Переменные окружения применяются для конфигурации: API_BASE_URL=http://localhost:3000, LOG_LEVEL=debug.
Для управления фичами (feature flags) в разных средах используется комбинация Arguments + Build Configuration. В Dev-схеме устанавливается аргумент -FeatureFlagNewOnboarding YES, а в Production — -FeatureFlagNewOnboarding NO (или аргумент отсутствует). В коде проверка: UserDefaults.standard.bool(forKey: "FeatureFlagNewOnboarding"). Этот подход позволяет постепенно включать фичи на staging без изменения кода и без коммита production-значений.
Важно: аргументы и переменные окружения Scheme переопределяют значения из Info.plist. Если в Info.plist указан API_URL, а в Scheme — API_URL=http://localhost для Run Action, при запуске из Xcode будет использовано значение из Scheme. При запуске с устройства (не из Xcode) — значение из Info.plist. Это удобно для локальной разработки, но нужно помнить, что переменные Scheme не попадают в сборку — они действуют только при запуске через Xcode.
import Foundation
struct AppEnvironment {
var apiBaseURL: String {
ProcessInfo.processInfo.environment["API_BASE_URL"]
?? Bundle.main.object(forInfoDictionaryKey: "API_BASE_URL") as? String
?? "https://api.production.com"
}
var isDebugMode: Bool {
ProcessInfo.processInfo.arguments.contains("-DebugModeEnabled")
}
var isNewOnboardingEnabled: Bool {
UserDefaults.standard.bool(forKey: "FeatureFlagNewOnboarding")
}
}
// Использование при старте
let env = AppEnvironment()
NetworkConfig.shared.configure(baseURL: env.apiBaseURL)
В CI/CD (GitHub Actions, Jenkins, GitLab CI) Scheme используется как основной аргумент команды xcodebuild. Пример: xcodebuild -workspace MyApp.xcworkspace -scheme MyApp -configuration Release -sdk iphoneos archive. Флаг -scheme указывает, какую схему использовать. xcodebuild читает все настройки из .xcscheme файла, включая build configuration, таргеты и порядок сборки. Это гарантирует, что CI/CD собирает приложение с теми же параметрами, что и локальная IDE.
Для CI/CD критичны Shared схемы. Если схема не Shared, xcodebuild не найдёт её в репозитории, и сборка упадёт с ошибкой "Scheme not found". Правило: перед настройкой CI/CD убедитесь, что все используемые схемы отмечены Shared. Второе правило: в CI/CD не используйте default scheme (Xcode автоматически выбирает первую схему) — всегда передавайте имя схемы явно через флаг -scheme.
Для параллельной сборки нескольких схем (например, приложение и watchOS-расширение) можно запускать xcodebuild последовательно или параллельно. Современные CI-системы позволяют распараллелить сборку разных схем через матрицу: одна джоба собирает iOS-приложение, вторая — watchOS-расширение. Это сокращает общее время сборки с 15 до 8 минут при двух параллельных агентах. В конце артефакты объединяются в единый .xcarchive с помощью xcodebuild -exportArchive.
#!/bin/bash — CI/CD сборка с xcodebuild
# 1. Очистка и сборка
xcodebuild clean archive \
-workspace "MyApp.xcworkspace" \
-scheme "MyApp Production" \
-configuration Release \
-sdk iphoneos \
-archivePath "build/MyApp.xcarchive" \
CODE_SIGN_STYLE="Manual" \
PROVISIONING_PROFILE_SPECIFIER="match AppStore"
# 2. Экспорт в IPA
xcodebuild -exportArchive \
-archivePath "build/MyApp.xcarchive" \
-exportPath "build/ipa" \
-exportOptionsPlist "ExportOptions.plist"
Часто задаваемые вопросы
Обычно достаточно 2-3 схем: Development (Debug), Staging (с аргументами для тестового сервера) и Production (Release). Для модульных библиотек — одна схема с настройками для тестирования. Не плодите схемы — каждая новая схема требует поддержки.
Build Configuration (Debug/Release) — это набор флагов компилятора, определённых в .xcconfig. Scheme — это набор действий, каждое из которых ссылается на Build Configuration. Схема говорит "при запуске используй Debug", конфигурация определяет "Debug — это без оптимизаций, с символами".
Аргументы попадают в ProcessInfo.processInfo.arguments и UserDefaults (если аргумент начинается с дефиса). Переменные окружения — в ProcessInfo.processInfo.environment. В коде: UserDefaults.standard.bool(forKey: "FeatureFlag") для аргументов вида -FeatureFlag YES.
Да, в Build Action можно добавить несколько таргетов. Например, схема "App + Watch + Widget" будет собирать все три таргета последовательно (если parallelizeBuildables=NO) или параллельно (YES). Для архивирования приложения достаточно основного таргета — остальные собираются как зависимости.
Swift Package Manager не заменяет схемы — схема по-прежнему определяет, с какой конфигурацией собирать SPM-зависимости, какие тесты запускать и как архивировать. SPM-пакеты могут иметь собственные схемы, которые автоматически импортируются в проект при добавлении пакета.
Итоги
Мы разработаем мобильное приложение под ключ
IT Sectr создаёт приложения для iOS и Android для стартапов и бизнеса с 2017 года. Мы проконсультируем вас и предложим наилучшее решение.
Читайте также