Scheme в Xcode е конфигурация, която определя как да се изгради, тества, профилира и архивира приложението за iOS, macOS, watchOS или tvOS. Всяка Scheme съдържа набор от действия (Build, Run, Test, Profile, Analyze, Archive) със собствени параметри, аргументи и променливи на средата. Според Apple Developer Documentation, 2025, Scheme е основният инструмент за управление на build конфигурациите в Xcode, като замества ръчното превключване на параметри. Xcode автоматично създава схема за всеки target при първото отваряне на проекта.
Основни положения
Scheme в Xcode е XML файл (с разширение .xcscheme), който описва последователността от действия и техните параметри за изграждане и анализ на приложението. Всяка Scheme е свързана с един или повече target-и и определя с каква конфигурация (Debug, Release, AdHoc) да се изпълни всяко действие. Scheme е аналог на Build Variant в Android, но с по-гъвкава структура: една схема може да съдържа различни target-и за различни действия.
Xcode автоматично създава схема за всеки target при първото отваряне на проекта. Името на схемата по подразбиране съвпада с името на target-а. Ако в проекта има тестов target, Xcode автоматично го добавя към Test действието на схемата на основния target. За проекти с няколко target-а (основно приложение + watchOS + extension) Xcode създава отделна схема за всеки, но може да се създаде и една схема, която изгражда всички target-и наведнъж.
Схемите се съхраняват в директорията xcshareddata/xcschemes/ (за shared) или xcuserdata/<user>/xcschemes/ (за private). Shared схемите попадат в Git и се използват от целия екип. Private схемите се съхраняват локално и не се синхронизират. Файлът .xcscheme има XML формат с коренен елемент <Scheme>. Вътре има блокове за всяко действие: BuildAction, TestAction, LaunchAction, ProfileAction, AnalyzeAction, ArchiveAction.
.xcscheme е XML файл, който може да се редактира ръчно или чрез Xcode. Основни елементи: <BuildAction> (списък на изгражданите target-и), <TestAction> (препратки към тестови target-и), <LaunchAction> (конфигурация за стартиране), <ProfileAction>, <AnalyzeAction>, <ArchiveAction>. Всеки блок съдържа атрибута buildConfiguration, който определя каква конфигурация (Debug/Release) да се използва за даденото действие.
Scheme се състои от шест действия, всяко от които може да се конфигурира независимо. Build Action определя кои target-и се изграждат и в какъв ред. 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 (с оптимизации, без информация за дебъгване). Разработчикът може да добавя персонализирани конфигурации чрез project.xcconfig.
Действието 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). При създаването се избира target-ът, за който се създава схемата. Ако схемата е избрана като „duplicate“, Xcode автоматично копира настройките от съществуващата схема. Новите схеми по подразбиране се запазват като 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) — разкрива недефинирано поведение, например препълване на signed int. Тези опции са налични в Edit Scheme → Run → Diagnostics и работят само за Debug компилации. Включването на всички санитайзери може да забави стартирането 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. Полезни са за лични конфигурации: например схема с включени всички санитайзери за конкретен разработчик. Private схемите не трябва да съдържат критични настройки, от които зависи изграждането на проекта — ако разработчикът напусне проекта, неговите private схеми ще изчезнат. Препоръка: всички схеми, използвани в CI/CD и от поне двама разработчици, да се правят Shared.
Управлението на схемите се извършва чрез Manage Schemes (Product → Scheme → Manage Schemes). В прозореца се показват всички схеми на проекта, техният статус (Shared/Private) и бутоните +/— за добавяне/премахване. Полето Shared превключва видимостта на схемата за екипа. При конфликт в Git (промени в .xcscheme от двама разработчици) трябва внимателно да се разреши сливането — XML файловете могат да съдържат различни идентификатори на target-и. Препоръчва се .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, target-ите и реда на изграждане. Това гарантира, че CI/CD изгражда приложението със същите параметри като локалната IDE.
За CI/CD са критични shared схемите. Ако една схема не е Shared, xcodebuild няма да я намери в хранилището и компилацията ще се провали с грешка „Scheme not found“. Правило: преди конфигурирането на CI/CD се уверете, че всички използвани схеми са отбелязани като Shared. Второ правило: в CI/CD не използвайте схемата по подразбиране (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 могат да се добавят няколко target-а. Например схемата „App + Watch + Widget“ ще изгради и трите target-а последователно (ако parallelizeBuildables=NO) или паралелно (YES). За архивирането на приложението е достатъчен основният target — останалите се изграждат като зависимости.
Swift Package Manager не замества схемите — схемата продължава да определя с каква конфигурация да се изградят SPM зависимостите, кои тестове да се стартират и как да се архивира. SPM пакетите могат да имат собствени схеми, които автоматично се импортират в проекта при добавяне на пакета.
Резюме
Ще разработим мобилно приложение под ключ
IT Sectr създава iOS и Android приложения за стартъпи и бизнеси от 2017 г. Ще ви консултираме и ще предложим най-доброто решение.
Прочетете също