En ausencia de macros de preprocesador, ¿hay alguna manera de definir indicadores específicos de esquemas prácticos a nivel de proyecto en el proyecto Xcode

174

Antes de Swift, definiría un conjunto de esquemas para las versiones alfa, beta y de distribución. Cada uno de estos esquemas tendría un conjunto de macros que se definieron para bloquear ciertos comportamientos a nivel de proyecto. El ejemplo más simple es la macro DEBUG = 1 que se define por defecto para todos los proyectos de Xcode en el esquema predeterminado para la compilación Ejecutar. Se podría consultar #ifdef DEBUG ... y tomar decisiones en el código en consecuencia, incluso compilar código no necesario.

Parece que este tipo de compuerta configuracional no es tan fácil con Swift, ya que las macros no son compatibles. ¿Alguien puede sugerir un enfoque comparable? No me importa si el código se compila per se. Sin embargo, me gustaría incluir características basadas en el esquema de compilación.

banDedo
fuente

Respuestas:

468

En Swift todavía puede usar las macros de preprocesador "# if / # else / # endif" (aunque más restringido), según los documentos de Apple . Aquí hay un ejemplo:

#if DEBUG
    let a = 2
#else
    let a = 3
#endif

Ahora, sin embargo, debe establecer el símbolo "DEPURAR" en otro lugar. Configúrelo en la sección "Compilador Swift - Banderas personalizadas", línea "Otras banderas Swift". Agrega el símbolo DEPURAR con el-D DEBUG entrada.

(Configuración de compilación -> Compilador Swift - Banderas personalizadas) ingrese la descripción de la imagen aquí

Como de costumbre, puede establecer un valor diferente cuando está en Debug o cuando está en Release.

Lo probé en código real; no parece ser reconocido en un patio de recreo.

Jean Le Moignan
fuente
55
Tenga en cuenta que también puede usar líneas #elseif para agregar más pruebas. Curiosamente, puede acceder a la definición pero no extraer nada de ella; es decir, defina -DDEBUG = 5 (o = "FOO") e intente imprimirlo con "println (DEBUG is (DEBUG)". Esa línea no genera errores, pero no hace nada.
David H
10
Nota: "Configuración integrada -> Compilador Swift -> Indicadores personalizados" no visible en la configuración de compilación "Básica". Debe mostrar la configuración de compilación "Todos" para que aparezca.
levibostian
77
@EugeneDubinin probablemente porque debe asegurarse de que $(inherited)se utiliza en la configuración de destino para heredar la configuración del proyecto.
DanSkeel
2
@DanSkeel buena captura, agregar $(inherited)hace que mi comentario sea irrelevante, ¡gracias!
Yevhen Dubinin
10
En Xcode 8 ahora también hay una configuración de "Condiciones de compilación activa" en la sección "Compilador rápido - Banderas personalizadas". Puede agregar banderas aquí sin necesidad de -D
Marcus
32

Nos topamos con un problema al no querer establecer indicadores rápidos del compilador porque no queríamos tener que configurarlos y mantenerlos actualizados para diferentes objetivos, etc. Además, en nuestra base de código mixto, no queríamos recordar para establecer nuestras banderas de manera apropiada todo el tiempo para cada idioma.

Para el nuestro, declaramos un archivo en ObjC

PreProcessorMacros.h

extern BOOL const DEBUG_BUILD;

En ellos

PreProcessorMacros.m

#ifdef DEBUG
    BOOL const DEBUG_BUILD = YES;
#else
    BOOL const DEBUG_BUILD = NO;
#endif

Luego, en su Encabezado de Puente Objective-C

#import "PreProcessorMacros.h"

Ahora, use esto en su base de código Swift

if DEBUG_BUILD {
    println("debug")
} else {
    println("release")
}

Esto definitivamente es una solución, pero resolvió nuestro problema, así que lo publiqué aquí con la esperanza de que ayude. No pretende sugerir que las respuestas existentes no sean válidas.

Logan
fuente
11
El objetivo de las macros es cambiar el código en función de la configuración de compilación. Está devolviendo el if al tiempo de ejecución, no necesita macro para eso.
Berik
18
@Berik: publiqué una solución válida con la esperanza de que también podría ayudar a otros que intentan resolver un aspecto de este problema, particularmente en proyectos en varios idiomas. Si su problema requiere no compilar código específico, está bien. También un comentario está bien, particularmente cuando informa a algunos por qué esta podría no ser la solución para ellos. También solicita que se tome nota en la respuesta sobre las limitaciones de este enfoque. El voto negativo es innecesario y desalienta las soluciones alternativas que podrían ser útiles para que otros resuelvan problemas similares. Además, op dice "No me importa si el código está compilado".
Logan
5

Solución más rápida para el método Logans. Establecer -D DEBUGen Other Swift Flagsde Swift Compiler - Custom Flagsla sección de configuración de generación de su objetivo.

Luego declare el siguiente método en alcance global:

#if DEBUG
let isDebugMode = true
#else
let isDebugMode = false
#endif

Ahora úsalo como

if isDebugMode {
    // Do debug stuff
}
Sahil Kapoor
fuente
1

Para mí, el elemento de depuración de " Condición de compilación activa " en "DEPURAR" funcionó.

Luego, el uso del trabajo clave DEBGU en #IF DEBUG funciona en modo de depuración y #ELSE en modo de liberación:

  1. Selecciona tu objetivo,
  2. En la pestaña Configuración de compilación, busque "Condición de compilación activa",
  3. Establezca el valor de su elemento "Depurar" en "YourKeyWord",
  4. Use simplemente como sigue:

    #if DEBUG
        print("You'r running in DEBUG mode!")
    #else
        print("You'r running in RELEASE mode!")
    #endif
Marjan Basiri
fuente
0

Estoy trabajando en una base de código de idioma mixto donde el código obj-c usa una macro para enviar mensajes de depuración a la consola (y esa macro se basa en nuestro indicador de preprocesador de depuración). Quería poder llamar a esa misma macro en el código rápido ...

  1. Creé un método de clase en una de mis clases obj-c que es un contenedor alrededor de esa macro.
  2. Agregué ese encabezado obj-c a nuestro archivo de encabezado de puente.
  3. Ahora mi código rápido llama a ese método de clase como un "proxy" de la macro obj-c.

Es un poco molesto que no pueda simplemente llamar a la macro directamente en el código rápido, pero al menos ahora solo tengo un lugar en el proyecto para preocuparme por activar / desactivar mi indicador de depuración.

ghostatron
fuente