Las Active Compilation Conditions son banderas que se pasan al compilador durante la compilación y permiten incluir o excluir bloques de código específicos del archivo binario final. Según la Documentación de Apple Developer (2026), Swift admite Active Compilation Conditions mediante la clave OTHER_SWIFT_FLAGS y la directiva #if. Active Compilation Conditions brindan a los desarrolladores la posibilidad de compilar diferentes versiones de código para depuración, pruebas y producción sin verificaciones en tiempo de ejecución.
Puntos clave
Active Compilation Conditions son banderas de compilación que determinan el conjunto de directivas de preprocesador activas durante la compilación. A diferencia de las banderas en tiempo de ejecución (verificación if (isDebug)), las condiciones de compilación excluyen físicamente el código inactivo del archivo binario, lo que proporciona ganancias de rendimiento y reduce el tamaño de la aplicación.
El mecanismo funciona a nivel de preprocesador o fases tempranas de compilación: el compilador recibe una lista de nombres activos y, al encontrar la directiva #if NAME, verifica si NAME está en esa lista. Si el nombre no está presente, el código dentro del bloque se ignora y no se compila.
Según el Blog de Swift.org (2025), el uso de Active Compilation Conditions en lugar de banderas en tiempo de ejecución reduce el tamaño del binario de lanzamiento en un promedio de 12-18% para proyectos con un sistema extenso de registro y herramientas de depuración. Esto es especialmente crítico para aplicaciones móviles con limitaciones de tamaño de archivo de instalación.
La principal diferencia con la compilación condicional a nivel de preprocesador de C/C++ es que las Active Compilation Conditions en Swift y Kotlin funcionan a nivel de AST (Árbol de Sintaxis Abstracta) del compilador, no a nivel de reemplazo de texto. Esto las hace más seguras y predecibles: cualquier error de sintaxis en una rama #if inactiva se detectará durante el análisis, no se manifestará en tiempo de ejecución.
Otra diferencia importante es que en Swift, la condición #if os(iOS) || os(macOS) se verifica en tiempo de compilación y funciona con nombres de plataforma, no con macros de preprocesador. Esto elimina toda una clase de errores relacionados con la inserción incorrecta de texto mediante #define, que son posibles en el preprocesador de C/C++. El compilador de Swift ve el AST, no el texto reemplazado, lo que hace que la depuración de la compilación condicional sea significativamente más fácil.
Swift admite Active Compilation Conditions mediante la directiva #if, que acepta una lista de nombres de banderas combinados con operadores lógicos &&, || y !. El compilador incluye el código dentro de #if ... #endif solo si la condición es verdadera.
Swift proporciona varias condiciones integradas: DEBUG (activo automáticamente en compilaciones de depuración), swift(>=5.0) (verificación de versión del compilador), canImport(UIKit) (verificación de disponibilidad del módulo) y targetEnvironment(simulator) (verificación de entorno). Estas condiciones no requieren configuración adicional.
// Condiciones integradas de Swift
#if DEBUG
print("Compilación de depuración — registro activo")
#endif
#if canImport(UIKit)
import UIKit
let screen = UIScreen.main.bounds
#elseif canImport(AppKit)
import AppKit
let screen = NSScreen.main?.frame
#endif
Los desarrolladores pueden agregar sus propias banderas a través de la configuración de compilación OTHER_SWIFT_FLAGS en Xcode. La bandera se especifica con el prefijo -D, por ejemplo -DBETA o -DANALYTICS_ENABLED. Se pueden configurar diferentes conjuntos de banderas para diferentes configuraciones (Debug, Release, Staging).
// Manejo de la bandera personalizada 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 admite condiciones de plataforma: os(iOS), os(macOS), os(tvOS), os(watchOS), os(Linux), os(Windows). Estas condiciones verifican la plataforma de compilación objetivo y permiten escribir código compartido entre múltiples plataformas Apple con bloques específicos de plataforma.
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
}
En el ecosistema Android, las Active Compilation Conditions se implementan mediante el sistema BuildConfig, productFlavors y banderas en build.gradle.kts. Kotlin no tiene un equivalente directo de la directiva #if a nivel de lenguaje, pero proporciona mecanismos alternativos.
El enfoque más común es agregar un buildConfigField para cada bandera: buildConfigField("boolean", "BETA", "true"). Estos campos se generan en la clase BuildConfig para cada variante de compilación por separado. El campo DEBUG ya está integrado y es automáticamente verdadero para las compilaciones de depuración.
// build.gradle.kts
android {
buildTypes {
debug {
buildConfigField("boolean", "BETA", "true")
}
release {
buildConfigField("boolean", "BETA", "false")
}
}
}
// Uso en código Kotlin
if (BuildConfig.BETA) {
enableBetaFeatures()
}
Gradle permite crear directorios sourceSets separados para cada sabor. Por ejemplo, src/demo/ y src/full/. Las clases con el mismo nombre en diferentes sourceSets se reemplazan entre sí al compilar el sabor correspondiente. Este es un mecanismo más potente que las banderas porque se pueden sobrescribir clases enteras.
// 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
}
Para Kotlin Multiplatform (KMP), está disponible la directiva expect/actual, que permite declarar declaraciones esperadas en código común y proporcionar implementaciones específicas de plataforma. Este es un mecanismo a nivel de compilador similar en efecto a las Active Compilation Conditions: el código inactivo no se compila para plataformas no adecuadas.
Las Active Compilation Conditions se utilizan en cuatro escenarios principales: depuración (registros, inspectores), pruebas A/B (banderas de funciones), adaptación de plataforma (código compartido iOS/macOS) y licencias (versiones gratuitas/de pago).
El escenario más común es el registro condicional. En las compilaciones de depuración, todos los registros se escriben en la consola; en las de lanzamiento, no se registra nada. El uso de #if DEBUG o BuildConfig.DEBUG garantiza que el binario de lanzamiento no contenga ni una sola llamada al registrador, incluso las inlineadas.
func logRequest(_ url: URL, _ statusCode: Int) {
#if DEBUG
Logger.debug("Request to \(url.absoluteString) returned \(statusCode)")
#endif
}
Si una nueva funcionalidad aún no está lista para producción pero ya existe en el código, se puede ocultar detrás de una bandera de compilación. A diferencia de las banderas de funciones en tiempo de ejecución, las banderas de compilación no sobrecargan la aplicación con verificaciones y no pueden ser activadas por el usuario.
Las Active Compilation Conditions deben usarse con moderación. Una cantidad excesiva de banderas hace que el código sea difícil de entender: el desarrollador no puede estar seguro de qué ramas se compilarán en un momento dado. Se recomienda documentar cada bandera en el README o en un archivo CONFIG.md dedicado.
En proyectos grandes con equipos distribuidos, es útil implementar validación automática de banderas en CI. Cada solicitud de extracción debe pasar la compilación con todas las combinaciones posibles de Active Compilation Conditions. Esto garantiza que el código bajo una bandera inactiva no se haya roto debido a la refactorización, y que ninguna rama de compilación condicional permanezca sin probar hasta el lanzamiento. Herramientas como xcresulttool (para iOS) y Gradle Build Scan (para Android) ayudan a automatizar este proceso.
Preguntas frecuentes
#if DEBUG es una directiva de compilación: si DEBUG no está activo, el código dentro del bloque no entra en el binario. if (isDebug) es una verificación en tiempo de ejecución: el código siempre se compila, la condición se verifica durante la ejecución. #if no deja rastros en la compilación de lanzamiento.
En la configuración de compilación del proyecto, busque Other Swift Flags (OTHER_SWIFT_FLAGS) y agregue una nueva línea con la bandera: -DMY_FLAG. La bandera será visible para la directiva #if MY_FLAG. Se pueden establecer diferentes banderas para las configuraciones Debug y Release.
Kotlin/JVM no tiene un equivalente directo. En su lugar, se utilizan campos BuildConfig (verificación en tiempo de ejecución, pero ProGuard puede eliminar el código no utilizado). En Kotlin Multiplatform — la directiva expect/actual a nivel de declaraciones.
Sí, Swift admite operadores lógicos: #if DEBUG && BETA, #if os(iOS) || os(tvOS), #if !RELEASE. Las condiciones se pueden agrupar con paréntesis para lógica compleja. AND y OR funcionan según las reglas estándar de cortocircuito.
Las vistas previas de SwiftUI se compilan en un proceso separado con banderas diferentes al objetivo principal. DEBUG puede no estar activo. Solución: use targetEnvironment(simulator) para el código de vista previa o extraiga la lógica condicional en métodos separados.
Resumen
Desarrollaremos una aplicación móvil llave en mano
IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.
Lea también