Na ausência de macros do pré-processador, existe uma maneira de definir sinalizadores específicos de esquema prático no nível do projeto no projeto Xcode

174

Antes do Swift, eu definiria um conjunto de esquemas para builds alfa, beta e distribuição. Cada um desses esquemas teria um conjunto de macros definidas para bloquear determinados comportamentos no nível do projeto. O exemplo mais simples é a macro DEBUG = 1 definida por padrão para todos os projetos do Xcode no esquema padrão da construção Executar. Pode-se consultar #ifdef DEBUG ... e tomar decisões no código de acordo, compilando até mesmo códigos não necessários.

Parece que esse tipo de bloqueio de configuração não é tão fácil com o uso rápido, pois as macros não são suportadas. Alguém pode sugerir uma abordagem comparável, não me importo se o código for compilado, por si só. Eu gostaria de bloquear os recursos com base no esquema de compilação.

banDedo
fonte

Respostas:

468

No Swift, você ainda pode usar as macros de pré-processador "# if / # else / # endif" (embora mais restritas), conforme documentos da Apple . Aqui está um exemplo:

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

Agora, você deve definir o símbolo "DEBUG" em outro lugar. Defina-o na seção "Swift Compiler - Custom Flags", na linha "Other Swift Flags". Você adiciona o símbolo DEBUG à -D DEBUGentrada.

(Configurações de compilação -> Swift Compiler - Sinalizadores personalizados) insira a descrição da imagem aqui

Como de costume, você pode definir um valor diferente no Debug ou no Release.

Eu testei em código real; não parece ser reconhecido em um playground.

Jean Le Moignan
fonte
5
Observe que você também pode usar as linhas #elseif para adicionar mais testes. Curiosamente, você pode acessar a definição, mas não extrair nada dela; ou seja, defina -DDEBUG = 5 (ou = "FOO") e tente imprimi-lo com "println (DEBUG é (DEBUG)". Essa linha não gera erros, mas não faz nada.
David H
10
Nota: "Configurações integradas -> Swift Compiler -> Sinalizadores personalizados" não está visível nas configurações de compilação "Básicas". É necessário mostrar "Todas" as configurações de compilação para que apareça.
levibostian
7
@EugeneDubinin provavelmente porque você deve se certificar de que $(inherited)é usado nas configurações de destino para herdar as configurações do projeto.
DanSkeel
2
@DanSkeel boa captura, adicionando $(inherited)torna meu comentário irrelevante, obrigado!
Yevhen Dubinin
10
No Xcode 8, agora também há uma configuração "Condições de compilação ativa" na seção "Swift Compiler - Custom Flags". Você pode adicionar sinalizadores aqui sem a necessidade de -D
Marcus
32

Ocorreu um problema ao não querer definir sinalizadores de compilador rápidos, porque não queríamos defini-los e mantê-los atualizados para diferentes destinos etc. Além disso, em nossa base de código mista, não queríamos lembrar para definir nossas bandeiras adequadamente o tempo todo para cada idioma.

Para o nosso, declaramos um arquivo no ObjC

PreProcessorMacros.h

extern BOOL const DEBUG_BUILD;

Neles

PreProcessorMacros.m

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

Em seguida, no cabeçalho de ponte Objective-C

#import "PreProcessorMacros.h"

Agora, use isso na sua base de código Swift

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

Definitivamente, é uma solução alternativa, mas resolveu o nosso problema, então eu o publiquei aqui na esperança de que ele ajude. Não pretende sugerir que as respostas existentes são inválidas.

Logan
fonte
11
O objetivo das macros é alterar o código com base na configuração da compilação. Você está trazendo o if de volta ao tempo de execução, não precisa de macros para isso.
Berik
18
@Berik - Publiquei uma solução válida na esperança de que também ajude outras pessoas a tentar resolver um aspecto desse problema, principalmente em projetos multilíngues. Se o seu problema exigir não compilar código específico, tudo bem. Além disso, um comentário é bom, principalmente quando informa alguns motivos pelos quais essa pode não ser a solução para eles. Também pedindo para fazer uma anotação na resposta sobre as limitações dessa abordagem. A redução de votos é desnecessária e desencoraja soluções alternativas que podem ser úteis para outras pessoas que resolvem problemas semelhantes. Além disso, op diz "Eu não me importo se o código for compilado".
Logan
5

Solução mais rápida para o método Logans. Situado -D DEBUGno Other Swift Flagsde Swift Compiler - Custom Flagsseção em configurações de compilação de seu alvo.

Em seguida, declare o seguinte método no escopo global:

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

Agora use-o como

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

Para mim, defina o item de depuração de " Condição de compilação ativa " como "DEBUG" funcionou.

Em seguida, usando a chave DEBGU, o trabalho em #IF DEBUG funciona no modo de depuração e #ELSE no modo de liberação:

  1. Selecione seu alvo,
  2. Na guia Configuração de compilação, procure "Condição de compilação ativa",
  3. Defina o valor do item "Debug" para "YourKeyWord",
  4. Use simplesmente como segue:

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

Estou trabalhando em uma base de código de idioma misto onde o código obj-c usa uma macro para enviar mensagens de depuração para o console (e essa macro depende de nosso sinalizador de pré-processador de depuração). Eu queria poder chamar essa mesma macro no código swift ...

  1. Criei um método de classe em uma das minhas classes obj-c que é um invólucro em torno dessa macro.
  2. Eu adicionei esse cabeçalho obj-c ao nosso arquivo de cabeçalho da ponte.
  3. Agora, meu código rápido chama esse método de classe como um "proxy" para a macro obj-c.

É um pouco irritante que eu não possa simplesmente chamar a macro diretamente no código swift, mas pelo menos agora só tenho um lugar no projeto para me preocupar em ativar / desativar meu sinalizador de depuração.

ghostatron
fonte