Scheme: cos'è, configurazione ed esecuzione in Xcode

Autore: IT Sectr Pubblicato: 2026-05-30 Tempo di lettura: 9 min

Uno Scheme in Xcode è una configurazione che definisce come compilare, testare, profilare e archiviare un'app per iOS, macOS, watchOS o tvOS. Ogni Scheme contiene un insieme di azioni (Build, Run, Test, Profile, Analyze, Archive) con i propri parametri, argomenti e variabili d'ambiente. Secondo la documentazione per sviluppatori Apple, 2025, Scheme è lo strumento principale per gestire le configurazioni di build in Xcode, sostituendo la commutazione manuale dei parametri. Xcode crea automaticamente uno schema per ogni target alla prima apertura del progetto.

Punti chiave

  • Scheme è una configurazione di Xcode con un insieme di azioni per compilare, testare e archiviare.
  • Build compila i target con una configurazione data (Debug o Release).
  • Run avvia l'app con argomenti, variabili d'ambiente e punto di ingresso.
  • Test esegue test unitari e UI con un insieme di test selezionato.
  • Archive compila per la pubblicazione sull'App Store con configurazione di produzione.

Che cos'è uno Scheme in Xcode?

Scheme in Xcode è un file XML (con estensione .xcscheme) che descrive una sequenza di azioni e i loro parametri per compilare e analizzare un'app. Ogni Scheme è legato a uno o più target e definisce con quale configurazione (Debug, Release, AdHoc) eseguire ogni azione. Scheme è l'equivalente della Build Variant in Android, ma con una struttura più flessibile: uno schema può contenere target diversi per azioni diverse.

Xcode crea automaticamente uno schema per ogni target alla prima apertura del progetto. Il nome dello schema per impostazione predefinita coincide con il nome del target. Se il progetto ha un target di test, Xcode lo aggiunge automaticamente all'azione Test dello schema del target principale. Per i progetti con più target (app principale + watchOS + estensione), Xcode crea uno schema separato per ciascuno, ma è possibile creare anche un unico schema che compila tutti i target contemporaneamente.

Gli schemi sono archiviati nella directory xcshareddata/xcschemes/ (per shared) o xcuserdata/<user>/xcschemes/ (per private). Gli schemi shared finiscono in Git e vengono usati da tutto il team. Gli schemi private sono archiviati localmente e non vengono sincronizzati. Il file .xcscheme ha un formato XML con elemento radice <Scheme>. All'interno ci sono blocchi per ogni azione: BuildAction, TestAction, LaunchAction, ProfileAction, AnalyzeAction, ArchiveAction.

Struttura del file .xcscheme

.xcscheme è un file XML che può essere modificato manualmente o tramite Xcode. Gli elementi principali: <BuildAction> (elenco dei target da compilare), <TestAction> (collegamenti ai target di test), <LaunchAction> (configurazione di avvio), <ProfileAction>, <AnalyzeAction>, <ArchiveAction>. Ogni blocco contiene l'attributo buildConfiguration, che determina quale configurazione (Debug/Release) usare per l'azione data.

Azioni dello Scheme: Build, Run, Test, Profile, Analyze, Archive

Scheme è composto da sei azioni, ognuna configurabile in modo indipendente. L'azione Build determina quali target vengono compilati e in quale ordine. L'azione Run determina come viene avviata l'app: con quali argomenti, variabili d'ambiente e quale configurazione. L'azione Test determina quali test vengono eseguiti e quali opzioni di copertura del codice sono attive. L'azione Profile avvia con gli strumenti Instruments per il profiling. L'azione Analyze esegue l'analisi statica del codice con Clang Static Analyzer. L'azione Archive compila per la pubblicazione sull'App Store o la distribuzione AdHoc.

Per ogni azione è possibile impostare una build configuration separata. Di solito si usa Debug per Run e Test e Release per Archive. La build configuration definisce un insieme di flag del compilatore, ottimizzazioni e informazioni di debug. Xcode fornisce due configurazioni standard: Debug (senza ottimizzazioni, con simboli di debug) e Release (con ottimizzazioni, senza informazioni di debug). Lo sviluppatore può aggiungere configurazioni personalizzate tramite project.xcconfig.

L'azione Archive è particolarmente importante: crea un .xcarchive che viene poi esportato in un .ipa per l'App Store o AdHoc. L'azione Archive usa la configurazione Release per impostazione predefinita, ma si può passare ad AdHoc o Distribution. Nell'azione Archive è disponibile anche il flag revealArchiveInOrganizer: al termine dell'archiviazione, Xcode apre l'Organizer per ulteriori operazioni sull'archivio.

xml
<!-- Esempio di .xcscheme per un'app 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>

Creazione e configurazione di uno Scheme

Sanitizer diagnostici

La creazione di un nuovo schema avviene tramite il menu di Xcode: Product → Scheme → New Scheme o con il pulsante "+" nel pannello Scheme (accanto al pulsante Run). Alla creazione viene selezionato il target per cui si crea lo schema. Xcode copia automaticamente le impostazioni da uno schema esistente se viene selezionato come "duplicate". I nuovi schemi vengono salvati come private per impostazione predefinita: per pubblicarli al team è necessario abilitare Shared in Manage Schemes.

La finestra Edit Scheme (Product → Scheme → Edit Scheme) contiene sei schede corrispondenti al numero di azioni. In ogni scheda è possibile modificare build configuration, argomenti di avvio, variabili d'ambiente e flag diagnostici. Nella scheda Run sono disponibili le opzioni: executable (quale binario avviare), wait for executable to be launched (per il debug dei processi avviati), debugger (LLDB o None), launch arguments, environment variables e opzioni estese (Address Sanitizer, Thread Sanitizer, Main Thread Checker, Memory Management).

Per la diagnostica, Address Sanitizer (ASan) rileva accessi fuori dai limiti, use-after-free e altri errori di memoria nel codice C/C++/ObjC. Thread Sanitizer (TSan) rileva le race condition (data races) nel codice multithread. Undefined Behavior Sanitizer (UBSan) rileva comportamenti non definiti, come l'overflow di un int con segno. Queste opzioni sono disponibili in Edit Scheme → Run → Diagnostics e funzionano solo per i build Debug. Abilitare tutti i sanitizer può rallentare l'avvio di 2-3 volte, quindi si consiglia di abilitarli selettivamente.

Clonazione dello schema per ambienti diversi

Una pratica tipica è creare schemi separati per ogni ambiente: Dev, Staging, Production. Ogni schema usa la stessa Build Configuration (Debug per Dev, Release per Production), ma argomenti di avvio diversi: -FIRAnalyticsDebugEnabled, -com.apple.CoreData.SQLDebug 1 per Dev e la loro assenza per Production. Gli argomenti di avvio vengono passati a UserDefaults (ProcessInfo.processInfo.arguments) e sono disponibili in lettura all'avvio dell'app. Questo permette di cambiare l'URL del server, il livello di logging e le funzionalità senza modificare il codice.

Schemi Shared e Private: gestione tramite Git

Gli schemi shared sono archiviati in <project>.xcworkspace/xcshareddata/xcschemes/ o <project>.xcodeproj/xcshareddata/xcschemes/ e finiscono nel repository Git. Tutti gli sviluppatori del team vedono questi schemi in Xcode. Gli schemi shared sono l'unico modo per distribuire schemi all'interno del team. Se uno sviluppatore ha creato uno schema importante (ad esempio "Staging Archive") ma non lo ha contrassegnato come Shared, il resto del team non lo vedrà, il che crea confusione: ognuno creerà il proprio schema con le proprie impostazioni.

Gli schemi private sono archiviati in xcuserdata/<user>/xcschemes/ e non finiscono in Git. Sono utili per configurazioni personali: ad esempio, uno schema con tutti i sanitizer abilitati per un determinato sviluppatore. Gli schemi private non devono contenere impostazioni critiche da cui dipende la build del progetto: se lo sviluppatore lascia il progetto, i suoi schemi private spariranno. Raccomandazione: tutti gli schemi usati in CI/CD e da almeno due sviluppatori dovrebbero essere Shared.

La gestione degli schemi avviene tramite Manage Schemes (Product → Scheme → Manage Schemes). La finestra mostra tutti gli schemi del progetto, il loro stato (Shared/Private) e pulsanti +/− per aggiungere/rimuovere. La casella Shared commuta la visibilità dello schema per il team. In caso di conflitto Git (modifiche a .xcscheme da parte di due sviluppatori), è necessario risolvere il merge con attenzione: i file XML possono contenere identificatori di target diversi. Si consiglia di aggiungere .xcscheme ai file bloccati durante il merge (git lfs o .gitattributes).

Argomenti di avvio e variabili d'ambiente

Gli argomenti in Scheme sono stringhe passate all'app all'avvio (ProcessInfo.processInfo.arguments) e variabili d'ambiente (ProcessInfo.processInfo.environment). Gli argomenti vengono usati per i flag: -AppleLanguages (ru), -AppleLocale ru_RU per simulare la lingua russa, o -FIRDebugEnabled per abilitare il debug di Firebase. Le variabili d'ambiente vengono usate per la configurazione: API_BASE_URL=http://localhost:3000, LOG_LEVEL=debug.

Per gestire le funzionalità (feature flags) in ambienti diversi si usa una combinazione di Arguments + Build Configuration. Nello schema Dev si imposta l'argomento -FeatureFlagNewOnboarding YES, in Production — -FeatureFlagNewOnboarding NO (o l'argomento è assente). Nel codice il controllo è: UserDefaults.standard.bool(forKey: "FeatureFlagNewOnboarding"). Questo approccio permette di abilitare gradualmente le funzionalità su staging senza modificare il codice e senza committare i valori di produzione.

Importante: gli argomenti e le variabili d'ambiente dello Scheme sovrascrivono i valori di Info.plist. Se in Info.plist è indicato API_URL e in Scheme — API_URL=http://localhost per l'azione Run, all'avvio da Xcode verrà usato il valore dello Scheme. All'avvio su un dispositivo (non da Xcode) — il valore di Info.plist. Questo è comodo per lo sviluppo locale, ma va ricordato che le variabili dello Scheme non entrano nel build: agiscono solo all'avvio tramite 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")
    }
}

// Utilizzo all'avvio
let env = AppEnvironment()
NetworkConfig.shared.configure(baseURL: env.apiBaseURL)

Scheme in CI/CD: automazione tramite xcodebuild

In CI/CD (GitHub Actions, Jenkins, GitLab CI), Scheme viene usato come argomento principale del comando xcodebuild. Esempio: xcodebuild -workspace MyApp.xcworkspace -scheme MyApp -configuration Release -sdk iphoneos archive. Il flag -scheme indica quale schema usare. xcodebuild legge tutte le impostazioni dal file .xcscheme, inclusi build configuration, target e ordine di compilazione. Questo garantisce che il CI/CD compili l'app con gli stessi parametri dell'IDE locale.

Per il CI/CD sono critici gli schemi shared. Se lo schema non è Shared, xcodebuild non lo troverà nel repository e il build fallirà con l'errore "Scheme not found". Regola: prima di configurare il CI/CD, assicurati che tutti gli schemi utilizzati siano contrassegnati come Shared. Seconda regola: nel CI/CD non usare lo schema predefinito (Xcode seleziona automaticamente il primo schema) — passa sempre il nome dello schema esplicitamente tramite il flag -scheme.

Per compilare più schemi in parallelo (ad esempio, l'app e l'estensione watchOS), è possibile eseguire xcodebuild in sequenza o in parallelo. I sistemi CI moderni permettono di parallelizzare la compilazione di schemi diversi tramite una matrice: un job compila l'app iOS, il secondo l'estensione watchOS. Questo riduce il tempo totale di compilazione da 15 a 8 minuti con due agenti in parallelo. Alla fine gli artefatti vengono combinati in un unico .xcarchive tramite xcodebuild -exportArchive.

bash
#!/bin/bash — build CI/CD con xcodebuild
# 1. Pulizia e compilazione
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. Esportazione in IPA
xcodebuild -exportArchive \
  -archivePath "build/MyApp.xcarchive" \
  -exportPath "build/ipa" \
  -exportOptionsPlist "ExportOptions.plist"

Domande frequenti

Quanti schemi servono per un progetto tipico?

Di solito 2-3 schemi bastano: Development (Debug), Staging (con argomenti per il server di test) e Production (Release). Per le librerie modulari — uno schema con impostazioni di test. Non creare troppi schemi: ogni nuovo schema richiede manutenzione.

In cosa differisce Scheme da Build Configuration?

Build Configuration (Debug/Release) è un insieme di flag del compilatore definiti in .xcconfig. Scheme è un insieme di azioni, ognuna delle quali fa riferimento a una Build Configuration. Lo schema dice "all'avvio usa Debug", la configurazione definisce "Debug significa senza ottimizzazioni, con simboli".

Come passare gli argomenti dallo Scheme al codice?

Gli argomenti finiscono in ProcessInfo.processInfo.arguments e UserDefaults (se l'argomento inizia con un trattino). Le variabili d'ambiente finiscono in ProcessInfo.processInfo.environment. Nel codice: UserDefaults.standard.bool(forKey: "FeatureFlag") per argomenti della forma -FeatureFlag YES.

Si può avere uno schema per più target?

Sì, nella Build Action si possono aggiungere più target. Ad esempio, uno schema "App + Watch + Widget" compilerà tutti e tre i target in sequenza (se parallelizeBuildables=NO) o in parallelo (YES). Per archiviare l'app basta il target principale: gli altri vengono compilati come dipendenze.

Perché serve uno schema se si usa SPM?

Swift Package Manager non sostituisce gli schemi: lo schema continua a definire con quale configurazione compilare le dipendenze SPM, quali test eseguire e come archiviare. I pacchetti SPM possono avere schemi propri, che vengono importati automaticamente nel progetto quando si aggiunge il pacchetto.

Sintesi

  • Scheme è una configurazione XML delle azioni di Xcode: Build, Run, Test, Profile, Analyze, Archive.
  • Build Configuration (Debug/Release) viene impostata separatamente per ogni azione dello schema.
  • Gli schemi shared sono archiviati in Git e usati da tutto il team, i private solo localmente.
  • Gli argomenti e le variabili d'ambiente in Scheme permettono di cambiare ambiente senza modificare il codice.
  • CI/CD usa Scheme tramite xcodebuild -scheme per garantire l'identità del build.
  • La diagnostica (ASan, TSan, UBSan) si configura nello schema per trovare bug in fase di sviluppo.
  • Raccomandazione: mantieni 2-3 schemi shared per Dev/Staging/Production e non conservare schemi private nel repository.

Svilupperemo un'applicazione mobile chiavi in mano

IT Sectr crea applicazioni iOS e Android per startup e aziende dal 2017. Ti consulteremo e ti proporremo la soluzione migliore.

Discuti il progetto

Leggi anche