Active Compilation Conditions zijn vlaggen die in de bouwfase aan de compiler worden doorgegeven en het mogelijk maken bepaalde codeblokken in het uiteindelijke binaire bestand op te nemen of uit te sluiten. Volgens Apple Developer Documentation (2026) ondersteunt Swift Active Compilation Conditions via de sleutel OTHER_SWIFT_FLAGS en de #if-directive. Active Compilation Conditions geven ontwikkelaars de mogelijkheid om verschillende versies van code te bouwen voor debuggen, testen en productie zonder runtime-controles.
Belangrijkste punten
Active Compilation Conditions zijn compilatievlaggen die de set actieve preprocessor-directieven in de bouwfase bepalen. In tegenstelling tot runtime-vlaggen (controle if (isDebug)), sluiten compilatievoorwaarden inactieve code fysiek uit van het binaire bestand, wat de prestaties verbetert en de grootte van de app vermindert.
Het mechanisme werkt op het niveau van de preprocessor of vroege compilatiefasen: de compiler ontvangt een lijst met actieve namen en wanneer hij de directive #if NAME tegenkomt, controleert hij of NAME op deze lijst staat. Als de naam niet bestaat — wordt de code binnen het blok genegeerd en niet gecompileerd.
Volgens Swift.org Blog (2025) vermindert het gebruik van Active Compilation Conditions in plaats van runtime-vlaggen de grootte van het release-binaire bestand gemiddeld met 12-18% voor projecten met een geavanceerd logsysteem en debug-tools. Dit is vooral kritisch voor mobiele apps met beperkingen op de grootte van het installatiebestand.
Het belangrijkste verschil met conditionele compilatie op C/C++ preprocessorniveau — Active Compilation Conditions in Swift en Kotlin werken op het niveau van de compiler AST (Abstract Syntax Tree), niet op het niveau van tekstuele vervanging. Dit maakt ze veiliger en voorspelbaarder: elke syntaxisfout in een inactieve #if-tak wordt gedetecteerd in de parseerfase en verschijnt niet in runtime.
Een ander belangrijk verschil — in Swift wordt de voorwaarde #if os(iOS) || os(macOS) gecontroleerd in de compilatiefase en werkt het met platformnamen, niet met preprocessor-macro's. Dit elimineert een hele klasse bugs gerelateerd aan onjuiste tekstinvoeging via #define, die mogelijk zijn in de C/C++ preprocessor. De Swift-compiler ziet AST in plaats van vervangen tekst, wat het debuggen van conditionele compilatie aanzienlijk eenvoudiger maakt.
Swift ondersteunt Active Compilation Conditions via de #if-directive, die een lijst met vlaggenamen accepteert die zijn verbonden door logische operatoren &&, || en !. De compiler neemt code binnen #if ... #endif alleen op als de voorwaarde waar is.
Swift biedt verschillende ingebouwde voorwaarden: DEBUG (automatisch actief in debug-build), swift(>=5.0) (controle van compilerversie), canImport(UIKit) (controle van modulebeschikbaarheid) en targetEnvironment(simulator) (omgevingscontrole). Deze voorwaarden vereisen geen extra configuratie.
// Ingebouwde Swift-voorwaarden
#if DEBUG
print("Debug-build — loggen actief")
#endif
#if canImport(UIKit)
import UIKit
let screen = UIScreen.main.bounds
#elseif canImport(AppKit)
import AppKit
let screen = NSScreen.main?.frame
#endif
De ontwikkelaar kan eigen vlaggen toevoegen via Build Setting OTHER_SWIFT_FLAGS in Xcode. De vlag wordt gespecificeerd met het voorvoegsel -D, bijvoorbeeld -DBETA of -DANALYTICS_ENABLED. Voor verschillende configuraties (Debug, Release, Staging) kunnen verschillende sets vlaggen worden ingesteld.
// Afhandeling van aangepaste vlag BETA
#if BETA
let apiEndpoint = "https://beta.api.com"
let isLoggingEnabled = true
#else
let apiEndpoint = "https://api.com"
let isLoggingEnabled = false
#endif
func trackEvent(_ name: String) {
#if ANALYTICS_ENABLED
Analytics.log(name)
#endif
}
Swift ondersteunt platformvoorwaarden: os(iOS), os(macOS), os(tvOS), os(watchOS), os(Linux), os(Windows). Deze voorwaarden controleren het doelplatform van de build en maken het mogelijk gemeenschappelijke code te schrijven voor meerdere Apple-platforms met platformspecifieke blokken.
import Foundation
func getDeviceName() -> String {
#if os(iOS)
return UIDevice.current.name
#elseif os(macOS)
return Host.current.name ?? "Unknown"
#else
return "Other platform"
#endif
}
In het Android-ecosysteem worden Active Compilation Conditions geïmplementeerd via het BuildConfig-systeem, productFlavors en vlaggen in build.gradle.kts. Kotlin heeft geen directe tegenhanger van de #if-directive op taalniveau, maar biedt alternatieve mechanismen.
De meest voorkomende methode — voeg buildConfigField toe voor elke vlag: buildConfigField("boolean", "BETA", "true"). Deze velden worden gegenereerd in de BuildConfig-klasse voor elke Build Variant afzonderlijk. Het veld DEBUG is al ingebouwd en automatisch true voor debug-builds.
// build.gradle.kts
android {
buildTypes {
debug {
buildConfigField("boolean", "BETA", "true")
}
release {
buildConfigField("boolean", "BETA", "false")
}
}
}
// Gebruik in Kotlin-code
if (BuildConfig.BETA) {
enableBetaFeatures()
}
Gradle maakt het mogelijk aparte sourceSets-directories te maken voor elke flavor. Bijvoorbeeld src/demo/ en src/full/. Klassen met dezelfde naam in verschillende sourceSets vervangen elkaar bij het bouwen van de betreffende flavor. Dit is een krachtiger mechanisme dan vlaggen, omdat hele klassen kunnen worden overschreven.
// src/demo/java/com/example/Config.kt
object Config {
const val API_URL = "http://demo.api.com"
const val IS_BETA = true
}
// src/full/java/com/example/Config.kt
object Config {
const val API_URL = "https://full.api.com"
const val IS_BETA = false
}
Voor Kotlin Multiplatform (KMP) is de expect/actual-directive beschikbaar, waarmee verwachte declaraties in gemeenschappelijke code kunnen worden gedeclareerd en platformimplementaties kunnen worden geleverd. Dit is een mechanisme op compilatieniveau dat qua effect vergelijkbaar is met Active Compilation Conditions — inactieve code wordt niet gecompileerd voor ongeschikte platforms.
Active Compilation Conditions worden gebruikt in vier hoofscenario's: debuggen (logs, inspecteurs), A/B-testen (functievlaggen), platformaanpassing (iOS/macOS gemeenschappelijke code) en licensering (gratis/betaalde versies).
Het meest voorkomende scenario — conditioneel loggen. In een debug-build worden alle logs naar de console geschreven, in release — geen. Het gebruik van #if DEBUG of BuildConfig.DEBUG garandeert dat het release-binaire bestand geen enkele logger-aanroep bevat, zelfs geen inline.
func logRequest(_ url: URL, _ statusCode: Int) {
#if DEBUG
Logger.debug("Request to \(url.absoluteString) returned \(statusCode)")
#endif
}
Als een nieuwe functionaliteit nog niet klaar is voor productie maar al in de code zit, kan deze worden verborgen achter een compilatievlag. In tegenstelling tot runtime feature flags, belasten compilatievlaggen de app niet met controles en kunnen ze niet door de gebruiker worden ingeschakeld.
Active Compilation Conditions moeten met mate worden gebruikt. Een overmatig aantal vlaggen maakt code moeilijk te begrijpen: de ontwikkelaar kan niet zeker weten welke takken op dat moment worden gecompileerd. Het wordt aanbevolen elke vlag te documenteren in README of een speciaal CONFIG.md-bestand.
In grote projecten met een gedistribueerd team is het nuttig om automatische validatie van vlaggen in CI te implementeren. Elke pull request moet een build doorlopen met alle mogelijke combinaties van Active Compilation Conditions. Dit garandeert dat code onder een inactieve vlag niet is gebroken door refactoring en dat geen enkele conditionele compilatietak ongetest blijft tot de release. Tools zoals xcresulttool (voor iOS) en Gradle Build Scan (voor Android) helpen dit proces te automatiseren.
Veelgestelde vragen
#if DEBUG — is een compilatiedirective: als DEBUG niet actief is, komt code binnen het blok niet in het binaire bestand. if (isDebug) — runtime-controle: code wordt altijd gecompileerd, de voorwaarde wordt tijdens uitvoering gecontroleerd. #if laat geen sporen achter in een release-build.
Zoek in de Build Settings van het project Other Swift Flags (OTHER_SWIFT_FLAGS) en voeg een nieuwe regel toe met de vlag: -DMY_FLAG. De vlag is zichtbaar voor de #if MY_FLAG-directive. U kunt verschillende vlaggen instellen voor Debug- en Release-configuraties.
In Kotlin/JVM is er geen direct equivalent. In plaats daarvan worden BuildConfig-velden gebruikt (runtime-controle, maar ProGuard kan ongebruikte code verwijderen). In Kotlin Multiplatform — de expect/actual-directive op declaratieniveau.
Ja, Swift ondersteunt logische operatoren: #if DEBUG && BETA, #if os(iOS) || os(tvOS), #if !RELEASE. Voorwaarden kunnen worden gegroepeerd met haakjes voor complexe logica. AND en OR werken volgens standaard kortsluitregels.
SwiftUI-previews worden in een apart proces gebouwd met vlaggen die verschillen van de hoofd-target. DEBUG is mogelijk niet actief. Oplossing: gebruik targetEnvironment(simulator) voor previewcode of verplaats conditionele logica naar aparte methoden.
Samenvatting
We ontwikkelen een mobiele applicatie turnkey
IT Sectr creëert sinds 2017 iOS- en Android-applicaties voor startups en bedrijven. We adviseren u en stellen de beste oplossing voor.
Lees ook