Scheme: esență, configurare și rulare în Xcode

Autor: IT Sectr Publicat: 2026-05-30 Timp de citire: 9 min

Scheme în Xcode este o configurație care determină cum să construiești, testezi, profilezi și arhivezi aplicația pentru iOS, macOS, watchOS sau tvOS. Fiecare Scheme conține un set de acțiuni (Build, Run, Test, Profile, Analyze, Archive) cu propriile parametri, argumente și variabile de mediu. Potrivit Apple Developer Documentation, 2025, Scheme este instrumentul principal de gestionare a configurațiilor de build în Xcode, înlocuind comutarea manuală a parametrilor. Xcode creează automat o schemă pentru fiecare target la prima deschidere a proiectului.

Elementele esențiale

  • Scheme — configurația Xcode cu un set de acțiuni pentru build, testare și arhivare.
  • Build — compilarea target-urilor cu configurația specificată (Debug sau Release).
  • Run — rularea aplicației cu argumente, variabile de mediu și punct de intrare.
  • Test — rularea testelor unit și UI cu selectarea setului de teste.
  • Archive — build pentru publicarea în App Store cu configurația de production.

Ce este Scheme în Xcode?

Scheme în Xcode este un fișier XML (extensia .xcscheme) care descrie secvența de acțiuni și parametrii lor pentru construirea și analiza aplicației. Fiecare Scheme este legată de unul sau mai multe target-uri și determină cu ce configurație (Debug, Release, AdHoc) să fie executată fiecare acțiune. Scheme este echivalentul Build Variant din Android, dar cu o structură mai flexibilă: o singură schemă poate conține target-uri diferite pentru acțiuni diferite.

Xcode creează automat o schemă pentru fiecare target la prima deschidere a proiectului. Numele implicit al schemei coincide cu numele target-ului. Dacă proiectul are un target de test, Xcode îl adaugă automat în acțiunea Test a schemei target-ului principal. Pentru proiectele cu mai multe target-uri (aplicația principală + watchOS + extension) Xcode creează o schemă separată pentru fiecare, dar se poate crea o singură schemă care construiește toate target-urile simultan.

Schemele sunt stocate în directorul xcshareddata/xcschemes/ (pentru shared) sau xcuserdata/<user>/xcschemes/ (pentru private). Schemele shared intră în Git și sunt folosite de întreaga echipă. Schemele private sunt stocate local și nu se sincronizează. Fișierul .xcscheme are format XML cu elementul rădăcină <Scheme>. În interior se află blocuri pentru fiecare acțiune: BuildAction, TestAction, LaunchAction, ProfileAction, AnalyzeAction, ArchiveAction.

Structura fișierului .xcscheme

.xcscheme este un fișier XML care poate fi editat manual sau prin Xcode. Elementele principale: <BuildAction> (lista target-urilor de compilat), <TestAction> (referințe la target-urile de test), <LaunchAction> (configurația de lansare), <ProfileAction>, <AnalyzeAction>, <ArchiveAction>. Fiecare bloc conține atributul buildConfiguration, care determină ce configurație (Debug/Release) să fie folosită pentru această acțiune.

Acțiunile Scheme: Build, Run, Test, Profile, Analyze, Archive

Scheme constă din șase acțiuni, fiecare putând fi configurată independent. Build Action determină care target-uri sunt construite și în ce ordine. Run Action — cum se lansează aplicația: cu ce argumente, variabile de mediu și cu ce configurație. Test Action — ce teste se execută și ce opțiuni de code coverage sunt activate. Profile Action — lansarea cu instrumentele Instruments pentru profilare. Analyze Action — analiza statică a codului cu Clang Static Analyzer. Archive Action — build pentru publicarea în App Store sau distribuirea AdHoc.

Pentru fiecare acțiune se poate seta o build configuration separată. De obicei, pentru Run și Test se folosește Debug, iar pentru Archive — Release. Build configuration determină setul de flag-uri ale compilatorului, optimizările și informațiile de debug. Xcode oferă două configurații standard: Debug (fără optimizări, cu simboluri de debug) și Release (cu optimizări, fără informații de debug). Dezvoltatorul poate adăuga configurații personalizate prin project.xcconfig.

Acțiunea Archive este deosebit de importantă — creează un .xcarchive care apoi este exportat în .ipa pentru App Store sau AdHoc. Archive Action folosește implicit configurația Release, dar se poate comuta pe AdHoc sau Distribution. În Archive Action este disponibil și flag-ul revealArchiveInOrganizer — după finalizarea arhivării, Xcode deschide Organiser pentru acțiuni ulterioare cu arhiva.

xml
<!-- Exemplu .xcscheme pentru aplicația 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>

Crearea și configurarea Scheme

Sanitizerele de diagnostic

Crearea unei scheme noi se face prin meniul Xcode: Product → Scheme → New Scheme sau cu butonul „+“ în panoul Scheme (lângă butonul Run). La creare se selectează target-ul pentru care se creează schema. Dacă schema este selectată ca „duplicate“, Xcode copiază automat setările din schema existentă. Schemele noi sunt salvate implicit ca private — pentru publicarea în echipă trebuie activat Shared în Manage Schemes.

Fereastra Edit Scheme (Product → Scheme → Edit Scheme) conține șase file, câte una pentru fiecare acțiune. Pe fiecare filă se pot modifica build configuration, argumentele de lansare, variabilele de mediu și flag-urile de diagnostic. Pe fila Run sunt disponibile opțiunile: executable (ce binar să fie rulat), wait for executable to be launched (pentru debug-ul proceselor lansate), debugger (LLDB sau None), launch arguments, environment variables și opțiunile avansate (Address Sanitizer, Thread Sanitizer, Main Thread Checker, Memory Management).

Pentru diagnostic Address Sanitizer (ASan) — detectează ieșirea în afara limitelor tabloului, use-after-free și alte erori de memorie în codul C/C++/ObjC. Thread Sanitizer (TSan) — detectează stările de cursă (data races) în codul multi-threaded. Undefined Behavior Sanitizer (UBSan) — evidențiază comportamentul nedefinit, de exemplu depășirea unui int cu semn. Aceste opțiuni sunt disponibile în Edit Scheme → Run → Diagnostics și funcționează doar pentru build-urile Debug. Activarea tuturor sanitizerelor poate încetini lansarea de 2-3 ori, de aceea se recomandă activarea lor selectivă.

Clonarea schemei pentru medii diferite

Practica tipică — crearea de scheme separate pentru fiecare mediu: Dev, Staging, Production. Fiecare schemă folosește aceleași Build Configuration (Debug pentru Dev, Release pentru Production), dar argumente de lansare diferite: -FIRAnalyticsDebugEnabled, -com.apple.CoreData.SQLDebug 1 pentru Dev și absența lor pentru Production. Argumentele de lansare sunt transmise în UserDefaults (ProcessInfo.processInfo.arguments) și sunt disponibile pentru citire la pornirea aplicației. Acest lucru permite comutarea URL-ului serverului, a nivelului de logare și a funcțiilor fără modificarea codului.

Schemele Shared și Private: gestionarea prin Git

Schemele Shared sunt stocate în <project>.xcworkspace/xcshareddata/xcschemes/ sau <project>.xcodeproj/xcshareddata/xcschemes/ și intră în repository-ul Git. Toți dezvoltatorii echipei văd aceste scheme în Xcode. Schemele Shared sunt singura modalitate de a distribui schemele în echipă. Dacă un dezvoltator a creat o schemă importantă (de exemplu „Staging Archive“), dar nu a marcat-o ca Shared, restul echipei nu o va vedea, ceea ce duce la confuzie: fiecare își va crea propria schemă cu propriile setări.

Schemele Private sunt stocate în xcuserdata/<user>/xcschemes/ și nu intră în Git. Sunt utile pentru configurații personale: de exemplu, o schemă cu toate sanitizerele activate pentru un dezvoltator anume. Schemele private nu trebuie să conțină setări critice de care depinde build-ul proiectului — dacă dezvoltatorul părăsește proiectul, schemele lui private dispar. Recomandare: toate schemele folosite în CI/CD și de cel puțin doi dezvoltatori să fie Shared.

Gestionarea schemelor se face prin Manage Schemes (Product → Scheme → Manage Schemes). În fereastră sunt afișate toate schemele proiectului, statusul lor (Shared/Private) și butoanele +/— pentru adăugare/ștergere. Bifarea Shared comută vizibilitatea schemei pentru echipă. La un conflict Git (modificări în .xcscheme de la doi dezvoltatori) trebuie rezolvată cu atenție îmbinarea — fișierele XML pot conține identificatori diferiți ai target-urilor. Se recomandă adăugarea .xcscheme în fișierele blocate la merge (git lfs sau .gitattributes).

Argumentele de lansare și variabilele de mediu

Arguments în Scheme sunt șirurile care sunt transmise aplicației la lansare (ProcessInfo.processInfo.arguments) și variabilele de mediu (ProcessInfo.processInfo.environment). Argumentele sunt folosite pentru flag-uri: -AppleLanguages (ru), -AppleLocale ru_RU pentru simularea localizării ruse sau -FIRDebugEnabled pentru activarea debug-ului Firebase. Variabilele de mediu se aplică pentru configurare: API_BASE_URL=http://localhost:3000, LOG_LEVEL=debug.

Pentru gestionarea funcțiilor (feature flags) în medii diferite se folosește combinația Arguments + Build Configuration. În schema Dev se setează argumentul -FeatureFlagNewOnboarding YES, iar în Production — -FeatureFlagNewOnboarding NO (sau argumentul lipsește). În cod, verificarea: UserDefaults.standard.bool(forKey: "FeatureFlagNewOnboarding"). Această abordare permite activarea treptată a funcțiilor în staging fără modificarea codului și fără commit-ul valorilor de production.

Important: argumentele și variabilele de mediu din Scheme suprascriu valorile din Info.plist. Dacă în Info.plist este specificat API_URL, iar în Scheme — API_URL=http://localhost pentru Run Action, la lansarea din Xcode va fi folosită valoarea din Scheme. La lansarea de pe dispozitiv (nu din Xcode) — valoarea din Info.plist. Este convenabil pentru dezvoltarea locală, dar trebuie reținut că variabilele Scheme nu intră în build — ele acționează doar la lansarea prin Xcode.

swift
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")
    }
}

// Folosit la pornire
let env = AppEnvironment()
NetworkConfig.shared.configure(baseURL: env.apiBaseURL)

Scheme în CI/CD: automatizare prin xcodebuild

În CI/CD (GitHub Actions, Jenkins, GitLab CI) Scheme este folosită ca argument principal al comenzii xcodebuild. Exemplu: xcodebuild -workspace MyApp.xcworkspace -scheme MyApp -configuration Release -sdk iphoneos archive. Flag-ul -scheme indică ce schemă să fie folosită. xcodebuild citește toate setările din fișierul .xcscheme, inclusiv build configuration, target-urile și ordinea de build. Aceasta garantează că CI/CD construiește aplicația cu aceiași parametri ca IDE-ul local.

Pentru CI/CD sunt critice schemele Shared. Dacă schema nu este Shared, xcodebuild nu o va găsi în repository, iar build-ul va eșua cu eroarea „Scheme not found“. Regulă: înainte de configurarea CI/CD asigură-te că toate schemele folosite sunt marcate ca Shared. A doua regulă: în CI/CD nu folosi schema implicită (Xcode selectează automat prima schemă) — transmite întotdeauna numele schemei explicit prin flag-ul -scheme.

Pentru build-ul paralel al mai multor scheme (de exemplu, aplicația și extensia watchOS) se poate rula xcodebuild secvențial sau paralel. Sistemele CI moderne permit paralelizarea build-ului diferitelor scheme printr-o matrice: un job construiește aplicația iOS, al doilea — extensia watchOS. Aceasta reduce timpul total de build de la 15 la 8 minute cu doi agenți paraleli. La final, artefactele sunt combinate într-un singur .xcarchive cu ajutorul xcodebuild -exportArchive.

bash
#!/bin/bash — construcție CI/CD cu xcodebuild
# 1. Curățare și build
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. Export în IPA
xcodebuild -exportArchive \
  -archivePath "build/MyApp.xcarchive" \
  -exportPath "build/ipa" \
  -exportOptionsPlist "ExportOptions.plist"

Întrebări frecvente

Câte scheme sunt necesare pentru un proiect tipic?

De obicei sunt suficiente 2-3 scheme: Development (Debug), Staging (cu argumente pentru serverul de test) și Production (Release). Pentru bibliotecile modulare — o schemă cu setări pentru testare. Nu înmulți schemele — fiecare schemă nouă necesită întreținere.

Prin ce diferă Scheme de Build Configuration?

Build Configuration (Debug/Release) — este un set de flag-uri ale compilatorului definite în .xcconfig. Scheme — este un set de acțiuni, fiecare referindu-se la Build Configuration. Schema spune „la lansare folosește Debug“, configurația definește „Debug înseamnă fără optimizări, cu simboluri“.

Cum se transmit argumentele din Scheme în cod?

Argumentele ajung în ProcessInfo.processInfo.arguments și UserDefaults (dacă argumentul începe cu o liniuță). Variabilele de mediu — în ProcessInfo.processInfo.environment. În cod: UserDefaults.standard.bool(forKey: "FeatureFlag") pentru argumente de forma -FeatureFlag YES.

Se poate avea o schemă pentru mai multe target-uri?

Da, în Build Action se pot adăuga mai multe target-uri. De exemplu, schema „App + Watch + Widget“ va construi toate cele trei target-uri secvențial (dacă parallelizeBuildables=NO) sau paralel (YES). Pentru arhivarea aplicației este suficient target-ul principal — celelalte sunt construite ca dependențe.

De ce este necesară schema dacă se folosește SPM?

Swift Package Manager nu înlocuiește schemele — schema determină în continuare cu ce configurație să fie construite dependențele SPM, ce teste să fie rulate și cum să se arhiveze. Pachetele SPM pot avea propriile scheme, care sunt importate automat în proiect la adăugarea pachetului.

Concluzii

  • Scheme — configurația XML a acțiunilor Xcode: Build, Run, Test, Profile, Analyze, Archive.
  • Build Configuration (Debug/Release) se setează separat pentru fiecare acțiune a schemei.
  • Schemele Shared sunt stocate în Git și folosite de întreaga echipă, private — doar local.
  • Argumentele și variabilele de mediu din Scheme permit comutarea mediului fără modificarea codului.
  • CI/CD folosește Scheme prin xcodebuild -scheme pentru a garanta identitatea build-ului.
  • Diagnostics (ASan, TSan, UBSan) se configurează în schemă pentru găsirea bug-urilor în etapa de dezvoltare.
  • Recomandare: păstrează 2-3 scheme Shared pentru Dev/Staging/Production și nu stoca schemele private în repository.

Vom dezvolta o aplicație mobilă la cheie

IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.

Discutați proiectul

Citiți și