Em C / C ++ / Objective C, você pode definir uma macro usando pré-processadores do compilador. Além disso, você pode incluir / excluir algumas partes do código usando pré-processadores do compilador.
#ifdef DEBUG
// Debug-only code
#endif
Existe uma solução semelhante no Swift?
Respostas:
Sim, você pode fazer isso.
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:
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 DEBUG
entrada.Como de costume, você pode definir um valor diferente no Debug ou no Release.
Eu testei em código real e funciona; embora não pareça ser reconhecido em um playground.
Você pode ler meu post original aqui .
NOTA IMPORTANTE:
-DDEBUG=1
não funciona. Só-D DEBUG
funciona. Parece que o compilador está ignorando um sinalizador com um valor específico.fonte
-D DEBUG
como indicado acima, você também precisa definirDEBUG=1
emApple LLVM 6.0 - Preprocessing
->Preprocessor Macros
.-DDEBUG
esta resposta: stackoverflow.com/a/24112024/747369 .DEBUG=1
aPreprocessor Macros
, se você não quiser usá-lo em código Objective-C.Conforme declarado no Apple Docs
Consegui alcançar o que queria usando configurações de compilação personalizadas:
Veja como você verifica o destino:
Testado usando o Swift 2.2
fonte
-DLOCAL
, no meu#if LOCAl #else #endif
, ele cai na#else
seção. Dupliquei o destino originalAppTarget
e o renomeei paraAppTargetLocal
& defina seu sinalizador personalizado.#if LOCAL
, o resultado pretendido quando corro com o simulador e cai#else
durante o teste. Eu quero que ele caia#if LOCAL
também durante os testes.Em muitas situações, você realmente não precisa de compilação condicional ; você só precisa de um comportamento condicional que possa ser ligado e desligado. Para isso, você pode usar uma variável de ambiente. Isso tem a enorme vantagem de você não precisar recompilar.
Você pode definir a variável de ambiente e ativá-la ou desativá-la facilmente no editor de esquema:
Você pode recuperar a variável de ambiente com NSProcessInfo:
Aqui está um exemplo da vida real. Meu aplicativo é executado apenas no dispositivo, porque usa a biblioteca de músicas, que não existe no Simulador. Como, então, tirar capturas de tela no Simulador para dispositivos que não possuo? Sem essas capturas de tela, não posso enviar para a AppStore.
Preciso de dados falsos e uma maneira diferente de processá-los . Eu tenho duas variáveis de ambiente: uma que, quando ativada, informa ao aplicativo para gerar os dados falsos a partir dos dados reais enquanto estiver sendo executado no meu dispositivo; o outro que, quando ligado, usa os dados falsos (e não a biblioteca de músicas que falta) durante a execução no Simulador. É fácil ativar ou desativar cada um desses modos especiais, graças às caixas de seleção de variáveis de ambiente no editor de esquema. E o bônus é que não posso usá-los acidentalmente na minha compilação na App Store, porque o arquivamento não possui variáveis de ambiente.
fonte
Uma grande mudança de
ifdef
substituição ocorreu com o Xcode 8. ou seja, o uso das Condições de Compilação Ativas .Consulte Construção e vinculação no Xcode 8 Release note .
Novas configurações de compilação
Nova configuração:
SWIFT_ACTIVE_COMPILATION_CONDITIONS
Anteriormente, tínhamos que declarar seus sinalizadores de compilação condicional em OTHER_SWIFT_FLAGS, lembrando-se de acrescentar "-D" à configuração. Por exemplo, para compilar condicionalmente com um valor MYFLAG:
O valor a ser adicionado à configuração
-DMYFLAG
Agora só precisamos passar o valor MYFLAG para a nova configuração. Hora de mover todos esses valores de compilação condicional!
Consulte o link abaixo para obter mais recursos do Swift Build Settings no Xcode 8: http://www.miqu.me/blog/2016/07/31/xcode-8-new-build-settings-and-analyzer-improvements/
fonte
A partir do Swift 4.1, se tudo o que você precisa é apenas verificar se o código foi criado com a configuração de depuração ou liberação, você pode usar as funções internas:
_isDebugAssertConfiguration()
(verdadeiro quando a otimização está definida como-Onone
)(não disponível no Swift 3+)_isReleaseAssertConfiguration()
(verdadeiro quando a otimização está definida como-O
)_isFastAssertConfiguration()
(verdadeiro quando a otimização está definida como-Ounchecked
)por exemplo
Comparado com macros de pré-processador,
-D DEBUG
sinalizador personalizado para usá-lo✗ Não documentado, o que significa que a função pode ser removida em qualquer atualização (mas deve ser segura na AppStore, pois o otimizador as transformará em constantes)
@testable
atributos , destino incerto no futuro Swift.✗ Usar if / else sempre gerará um aviso "Nunca será executado".
fonte
if _isDebugAssertConfiguration()
será avaliadoif false
no modo de liberação eif true
é o modo de depuração.Xcode 8 e acima
Use a configuração Condições de compilação ativa em Configurações de compilação / Compilador Swift - sinalizadores personalizados .
ALPHA
,BETA
etc.Em seguida, verifique-o com condições de compilação como esta:
fonte
Não há pré-processador Swift. (Por um lado, a substituição arbitrária de código quebra a segurança de tipo e de memória.)
No entanto, o Swift inclui opções de configuração em tempo de construção, para que você possa incluir condicionalmente código para determinadas plataformas ou estilos de construção ou em resposta a sinalizadores definidos com
-D
argumentos do compilador. Ao contrário do C, porém, uma seção compilada condicionalmente do seu código deve estar sintaticamente concluída. Há uma seção sobre isso em Usando o Swift With Cocoa e o Objective-C .Por exemplo:
fonte
INT_CONST
qualquer lugarfloat
que seja aceito. Swift não permitiria isso. Além disso, se você pudesse fazêvar floatVal = INT_CONST
-lo inevitavelmente, ele seria interrompido em algum momento mais tarde, quando o compilador espera um,Int
mas você o usa como umFloat
(o tipo defloatVal
seria inferido comoInt
). 10 elencos mais tarde e é apenas mais limpo para macros Remover ...Meus dois centavos para o Xcode 8:
a) Um sinalizador personalizado usando o
-D
prefixo funciona bem, mas ...b) Uso mais simples:
No Xcode 8, há uma nova seção: "Condições de Compilação Ativas", já com duas linhas, para depuração e lançamento.
Basta adicionar sua definição SEM
-D
.fonte
-D
.Constante isDebug com base nas condições de compilação ativa
Outra solução, talvez mais simples, que ainda resulta em um booleano que você pode passar para funções sem aplicar
#if
condicionais em toda a base de código é definirDEBUG
como um dos objetivos de construção do projetoActive Compilation Conditions
e incluir o seguinte (eu a defino como uma constante global):Constante isDebug com base nas configurações de otimização do compilador
Este conceito baseia-se na resposta de kennytm
A principal vantagem ao comparar com o kennytm é que isso não depende de métodos particulares ou não documentados.
No Swift 4 :
Comparado com as macros do pré-processador e a resposta do kennytm ,
-D DEBUG
sinalizador personalizado para usá-lo✓ Documentado , o que significa que a função seguirá os padrões normais de liberação / descontinuação da API.
✓ O uso de if / else não gerará um aviso "Nunca será executado".
fonte
Moignans responder aqui funciona bem. Aqui está outra informação, caso ajude,
Você pode negar as macros como abaixo,
fonte
Nos projetos Swift criados com o Xcode Versão 9.4.1, Swift 4.1
funciona por padrão porque nas macros do pré-processador DEBUG = 1 já foi definido pelo Xcode.
Então você pode usar #if DEBUG "fora da caixa".
A propósito, como usar os blocos de compilação de condições em geral está escrito no livro da Apple, The Swift Programming Language 4.1 (a seção Declarações de Controle do Compilador) e como escrever os sinalizadores de compilação e o que é equivalente às macros C do Swift. outro livro da Apple, usando Swift com cacau e objetivo C (na seção Diretivas de pré-processador)
Esperança no futuro A Apple escreverá o conteúdo mais detalhado e os índices de seus livros.
fonte
XCODE 9 E ACIMA
fonte
Após definir
DEBUG=1
asGCC_PREPROCESSOR_DEFINITIONS
configurações de compilação, prefiro usar uma função para fazer isso:E então apenas coloque nesta função qualquer bloco que eu queira omitir nas compilações de depuração:
A vantagem quando comparada com:
É que o compilador verifica a sintaxe do meu código, por isso tenho certeza de que a sintaxe está correta e se compila.
fonte
! [No Xcode 8 e acima, vá para a configuração de construção -> procure sinalizadores personalizados] 1
Em código
fonte
Fonte
fonte
@inlinable
na frentefunc
e essa seria a maneira mais elegante e idiomática do Swift. Nas versões de lançamento, seucode()
bloco será otimizado e eliminado por completo. Uma função semelhante é usada na estrutura NIO da Apple.Isso se baseia na resposta de Jon Willis que se baseia na afirmação, que só é executada nas compilações de depuração:
Meu caso de uso é para registrar instruções de impressão. Aqui está uma referência para a versão Release no iPhone X:
impressões:
Parece que o Swift 4 elimina completamente a chamada de função.
fonte