Active Compilation Conditions en el desarrollo de aplicaciones: conceptos clave y aplicación

Autor: IT Sectr Publicado: 2026-06-01 Tiempo de lectura: 8 min

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 — banderas de compilación personalizadas que determinan qué bloques de código se compilan en el binario final.
  • Swift utiliza la clave OTHER_SWIFT_FLAGS en la configuración de compilación de Xcode para establecer banderas con el prefijo -D.
  • La directiva #if verifica la presencia de una bandera: el código dentro de #if DEBUG se compila solo en compilaciones de depuración.
  • Android tiene una capacidad análoga: campos BuildConfig y productFlavors en Gradle.
  • Rendimiento — la compilación condicional no deja rastros en el binario de lanzamiento, a diferencia de las banderas en tiempo de ejecución.

Qué son las Active Compilation Conditions

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.

Active Compilation Conditions en Swift

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.

Condiciones integradas de Swift

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.

swift
// 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

Banderas personalizadas en Xcode

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).

swift
// 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
}

Condiciones de plataforma #if os()

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.

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

Alternativas en Android y Kotlin

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.

Campos BuildConfig como banderas

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.

kotlin
// build.gradle.kts
android {
    buildTypes {
        debug {
            buildConfigField("boolean", "BETA", "true")
        }
        release {
            buildConfigField("boolean", "BETA", "false")
        }
    }
}

// Uso en código Kotlin
if (BuildConfig.BETA) {
    enableBetaFeatures()
}

Source Sets y productFlavors

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.

kotlin
// 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.

Casos de uso y mejores prácticas

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).

Registro de depuración

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.

swift
func logRequest(_ url: URL, _ statusCode: Int) {
    #if DEBUG
        Logger.debug("Request to \(url.absoluteString) returned \(statusCode)")
    #endif
}

Banderas de funciones en tiempo de compilación

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.

  • Nuevas funciones — ocultar funcionalidad incompleta hasta el próximo lanzamiento sin eliminar código
  • Analítica — habilitar la recopilación adicional de métricas solo para evaluadores beta
  • SDK de terceros — excluir bibliotecas pesadas de la versión gratuita de la aplicación
  • Componentes de UI — mostrar pantallas experimentales solo en compilaciones de staging

Mejores prácticas

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.

  • Mínimo de banderas — no más de 5-7 condiciones activas por proyecto. Cada bandera es un punto de complejidad.
  • Convención de nombres — todas las banderas en MAYÚSCULAS, con prefijo del proyecto: MYAPP_BETA, MYAPP_ANALYTICS.
  • Revisión de código — cada adición de #if o buildConfigField debe pasar una revisión separada.
  • Pruebas — CI debe compilar todas las combinaciones posibles de banderas al menos una vez al día.

Preguntas frecuentes

¿Cuál es la diferencia entre #if DEBUG y if (isDebug) en Swift?

#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.

¿Cómo agrego una bandera personalizada en Xcode?

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.

¿Existe un equivalente en Kotlin de Swift #if?

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.

¿Se pueden combinar varias banderas en un solo #if?

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.

¿Por qué #if DEBUG no funciona en las vistas previas de SwiftUI?

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

  • Active Compilation Conditions — banderas de compilación que excluyen físicamente el código inactivo del binario sin verificaciones en tiempo de ejecución.
  • Swift admite #if con condiciones integradas (DEBUG, os, canImport) y banderas personalizadas mediante OTHER_SWIFT_FLAGS.
  • Android y Kotlin utilizan campos BuildConfig, productFlavors y el mecanismo expect/actual en KMP.
  • Rendimiento — la compilación condicional reduce el tamaño del binario en un 12-18% en proyectos con un sistema extenso de registro.
  • Banderas de funciones en tiempo de compilación no sobrecargan la aplicación con verificaciones y no pueden ser activadas por el usuario.
  • Recomendaciones — no más de 5-7 banderas por proyecto, convención de nombres con prefijo, pruebas obligatorias de todas las combinaciones en CI.

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.

Discutir el proyecto

Lea también