Em meu projeto atual, uso o UALogger . Ele não loga em produção , se você não perguntar explicitamente. E tem outros benefícios em relação ao NSLog simples, como níveis de gravidade (com DEBUG , INFO e etc.) prontos para uso. Bom trabalho!
Anton Gaenko
1
Para responder à sua pergunta sobre "terá um desempenho melhor?" Sim, é verdade, mas o rendimento que você obtém depende de quantos NSLog()você tem em seu aplicativo. NSLog()leva tempo para ser executado e adiciona sobrecarga ao tempo de execução do seu aplicativo. De qualquer forma, se ajudar no desempenho com uma macro de pré-processador DEBUG simples, devemos desabilitá-la.
Scott
Eu também sugeriria que se você tiver muitas instruções NSLog / print em seu código, isso pode sugerir que você deve passar algum tempo aprendendo mais sobre o depurador. Eu defino regularmente pontos de interrupção que imprimem informações nas quais estou interessado e continuo automaticamente. Sim, pode retardar um pouco a corrida, mas na maioria dos casos não é excessivo. Além disso, quebras condicionais para que você possa investigar quando algo inesperado aconteceu.
bshirley
Respostas:
127
Uma maneira de fazer isso é acessar as configurações de Build e, na configuração Debug, adicionar um valor ao valor "Macros de pré-processador" como:
DEBUG_MODE=1
Certifique-se de fazer isso apenas para a configuração de depuração e não para versões Beta ou de lançamento. Então, em um arquivo de cabeçalho comum, você pode fazer algo como:
Agora, em vez de NSLog usar em DLogtodos os lugares. Ao testar e depurar, você receberá mensagens de depuração. Quando você está pronto para lançar um beta ou lançamento final, todas essas DLoglinhas ficam vazias automaticamente e nada é emitido. Desta forma, não há configuração manual de variáveis ou comentários de NSLogsobrigatórios. Escolher seu alvo de construção cuida disso.
No Xcode 4.5 ele dá um aviso que diz: "A declaração implícita da função 'DLog' é inválida no C99" então isso não funciona.
Sergey Grischyov
2
@SergiusGee: Você obtém o aviso de declaração implícita se a declaração para a função não puder ser encontrada e, nesse caso, ele pensa que você está tentando declará-la. Certifique-se de que sua classe tenha acesso ao arquivo de cabeçalho onde está declarado.
sudo rm -rf
1
Não aceito o logout, pois isso impede que você receba relatórios de erro melhores dos usuários. use registro assíncrono e níveis de log para limitar o impacto de desempenho a quase zero! (ver cacau lenhador ou java's log4j
Daij-Djan
2
Eu escolheria #if em vez de #ifdef, pois DEBUG_MODE 0 ainda seguirá pelo caminho verdadeiro
Grady Player
1
isso não responde à pergunta
Martin Mlostek
117
Atualização para Xcode 5 e iOS 7
nota: para uma solução Xcode 7 / Swift 2.1 para remover as instruções print () em uma versão de lançamento, encontre minha resposta aqui .
Sim, você deve remover qualquer instrução NSLog em seu código de lançamento, pois isso apenas retarda o seu código e não tem qualquer utilidade em uma versão de lançamento. Felizmente, no Xcode 5 (iOS 7), é incrivelmente simples remover todas as suas instruções NSLog 'automaticamente' em compilações de lançamento. Então, por que não fazer?
Primeiro as 3 etapas a serem seguidas, depois alguma explicação
1) em seu projeto Xcode, localize o arquivo 'yourProjectName-prefix.pch' (normalmente você o encontrará no grupo 'arquivos de suporte', onde seu arquivo main.m está localizado
2) adicione essas 3 linhas no final do arquivo '.pch':
#ifndef DEBUG
#defineNSLog(...);#endif
3) teste a diferença entre a sua versão de 'depuração' e 'lançamento'. Uma maneira de fazer isso é através do 'esquema de edição' -> 'executar nome do aplicativo' -> na guia 'informações', selecione usando a caixa suspensa entre depuração e lançamento. Na versão de lançamento, você não verá nenhuma saída NSLog no console de depuração!
Como tudo isso funciona?
em primeiro lugar, deve-se saber que um pré-processador é relativamente 'burro' e apenas atua como um 'substituto de texto' antes de o compilador ser chamado. Ele substitui qualquer coisa que você '#define' pelo que segue a #definedeclaração.
#defineNSLog(...);
O (...)significa 'qualquer coisa' entre os colchetes (). Lembre-se também ;do final. Isso não é estritamente necessário, pois o compilador irá otimizar isso, mas eu gosto de colocá-lo lá, pois é mais 'correto'. Depois de nosso, #definenão há 'nada', então o pré-processador irá substituí-lo por 'nada', e então jogará fora a linha completa, começando em NSLog...até e incluindo o ;.
as declarações de definição podem ser tornadas condicionais usando #ifdef(se definido) ou #ifndef(se não definido)
aqui escrevemos #ifndef DEBUG, o que significa 'se o símbolo DEBUG não está definido'. O #ifdefou #ifndefprecisa ser 'fechado' com#endif
O Xcode 5 define por padrão o símbolo 'DEBUG' para nós quando o modo de construção é 'DEBUG'. Em 'release' isso não está definido. você pode verificar isso nas configurações do projeto, guia 'Configurações de compilação' -> role para baixo até a seção 'Apple LLVM 5.0 - Pré-processamento' -> macros do pré-processador. Você verá que o símbolo 'DEBUG' não está definido para versões de lançamento!
finalmente, o arquivo .pch é criado pelo Xcode automaticamente e automaticamente incluído em cada arquivo de origem durante o tempo de compilação. Portanto, é como se você tivesse colocado #definetudo em cada um de seus arquivos de origem.
Obrigado @Whasssaaahhh, funciona muito bem. Tenha cuidado para evitar colocar código em instruções de log! O pré-processador removerá todas as NSLoginstruções, desconsiderando o que está dentro.
Eric Platon
1
Se for um projeto mais antigo que não tem o sinalizador de depuração no pré-processador ou macros, é importante adicionar "debug = 1" para o projeto e não para o destino
Priebe
1
Além disso, não use NSLogcomo uma declaração de não fazer nada, por exemplo, em if(AllCool) NSLog(@"Cool!Do Nothing!"); else...vez disso, NSLogif(AllCool) {NSLog(@"Cool!Do Nothing!");} else...
coloque
33
Quase todas as respostas acima sugerem uma solução, mas não explicam o problema. Fiz uma pesquisa no google e descobri o motivo. Aqui está minha resposta:
Sim, se você comentar o NSLog em sua versão de lançamento, o desempenho será melhor. Porque NSLog é muito lento. Por quê? NSLog fará duas coisas 1) escrever mensagens de log no Apple System Logging (ASL), 2) se o aplicativo for executado em xcode, ele gravará em stderr também.
O principal problema está no primeiro. Para obter um thread seguro, cada vez que o NSLog é chamado, ele abre uma conexão com o recurso ASL , envia uma mensagem e fecha a conexão. A operação de conexão é muito cara. Outro motivo é que o NSLog gasta algum tempo para obter o registro de data e hora.
Além de todas as pessoas que sabiamente comentaram que não ligar NSLog()na produção é um pouco mais rápido, vou acrescentar que:
Todas essas NSLog()strings de saída são visíveis para qualquer pessoa que baixe seu aplicativo da loja e o execute com o dispositivo conectado a um mac executando o Xcode (por meio da janela do Organizer).
Dependendo das informações que você registra (e especialmente se seu aplicativo contata um servidor, faz autenticação, etc.), isso pode ser um sério problema de segurança .
obrigado pela informação - isto está em algum lugar do documento, ou você acabou de descobrir isso sozinho? Isso ainda é válido para impressão em Swift?
Ronny Webers
Não me lembro de ter lido nenhuma documentação. Acabei de instalar minha compilação arquivada (mesmo binário que enviei para a loja) no meu dispositivo e conectei-o ao Xcode. Não tenho ideia se é o mesmo para o de Swift print(), mas provavelmente é.
Nicolas Miari
@NicolasMiari O que você quer dizer com conectado ao Xcode? Como podemos conectar nosso binário ao Xcode, na verdade eu quero tentar o mesmo. Então, por favor, sugira. Obrigado.
iDevAmit
@iDeveloper Quero dizer, baixe seu aplicativo da AppStore para um dispositivo (por exemplo, um iPhone), conecte esse dispositivo ao Xcode via USB, inicie seu aplicativo e observe os logs na janela "Dispositivos" do Xcode.
Nicolas Miari
3
@Whasssaaahhh print não sai no console do dispositivo ... acabei de testar isso
Anish Parajuli 웃
13
Dentro da configuração padrão atual do projeto no Xcode, a NS_BLOCK_ASSERTIONSmacro será definida como 1 na versão de lançamento e DEBUG=1na versão de depuração.
Portanto, prefiro o método a seguir.
// NS_BLOCK_ASSERTIONS is defined by default, as shown in the screenshot above.// Or, you can define yourself Flags in the `Other C Flags` -> `Release`.#ifndef NS_BLOCK_ASSERTIONS
#define _DEBUG
#endif#ifdef _DEBUG
// for debug mode #defineDLog(fmt,...)NSLog(@"%s " fmt, __FUNCTION,##__VA_ARGS__) .../// something extra#else// for release mode#defineDLog(fmt,...)/* throw it away */.../// something extra#endif
Sim, você deve desativá-lo. Especialmente se você estiver tentando maximizar a velocidade do seu código. O NSLogging da esquerda e da direita polui o log do sistema que outros desenvolvedores podem estar tentando vasculhar e pode ter um grande impacto no código crítico de velocidade (dentro de loops, etc.) Eu deixei acidentalmente algumas mensagens de log em uma função recursiva uma vez e conseguiu lançar uma atualização com um "aumento de velocidade de 30%!" algumas semanas depois ... ;-)
Todas boas respostas, mas aqui está outro pequeno truque que você pode considerar usar, principalmente nas fases de desenvolvimento / teste do seu aplicativo.
Também pode ser útil para o código de lançamento do aplicativo, se você quiser apenas desligar SEU código de depuração, e não mensagens que podem indicar problemas fora do controle direto do seu código.
O truque:
Você pode desativar o NSLog por arquivo .m simplesmente incluindo a linha a seguir na parte superior do arquivo .m :
#defineNSLog(...)
( NOTA: NÃO coloque este arquivo .h, apenas o arquivo .m! )
Isso apenas faz com que o compilador avalie NSLog()expandindo a macro do pré-processador. A macro não faz nada além de remover os argumentos.
se quiser ligá-lo novamente, você sempre pode usar
#undefNSLog
Você poderia, por exemplo, apenas evitar chamadas para NSLog em torno de um determinado grupo de métodos fazendo algo como
NSLog é lento e não deve ser usado para compilações de lançamento. Uma macro simples como a abaixo irá desativá-la junto com quaisquer declarações que você possa ter que também devem ser desativadas. No caso menos comum em que você deseja NSLog em uma versão de lançamento, basta chamá-lo diretamente. Não se esqueça de adicionar "-DNDEBUG" às configurações de compilação de "outras sinalizações c".
Isso é bom, mas ainda tem o problema de toda a sobrecarga de chamada e de qualquer sobrecarga (e efeitos colaterais potenciais) de computar quaisquer argumentos passados para a Dlogfunção.
NSLog()
você tem em seu aplicativo.NSLog()
leva tempo para ser executado e adiciona sobrecarga ao tempo de execução do seu aplicativo. De qualquer forma, se ajudar no desempenho com uma macro de pré-processador DEBUG simples, devemos desabilitá-la.Respostas:
Uma maneira de fazer isso é acessar as configurações de Build e, na configuração Debug, adicionar um valor ao valor "Macros de pré-processador" como:
Certifique-se de fazer isso apenas para a configuração de depuração e não para versões Beta ou de lançamento. Então, em um arquivo de cabeçalho comum, você pode fazer algo como:
Agora, em vez de
NSLog
usar emDLog
todos os lugares. Ao testar e depurar, você receberá mensagens de depuração. Quando você está pronto para lançar um beta ou lançamento final, todas essasDLog
linhas ficam vazias automaticamente e nada é emitido. Desta forma, não há configuração manual de variáveis ou comentários deNSLogs
obrigatórios. Escolher seu alvo de construção cuida disso.fonte
Atualização para Xcode 5 e iOS 7
nota: para uma solução Xcode 7 / Swift 2.1 para remover as instruções print () em uma versão de lançamento, encontre minha resposta aqui .
Sim, você deve remover qualquer instrução NSLog em seu código de lançamento, pois isso apenas retarda o seu código e não tem qualquer utilidade em uma versão de lançamento. Felizmente, no Xcode 5 (iOS 7), é incrivelmente simples remover todas as suas instruções NSLog 'automaticamente' em compilações de lançamento. Então, por que não fazer?
Primeiro as 3 etapas a serem seguidas, depois alguma explicação
1) em seu projeto Xcode, localize o arquivo 'yourProjectName-prefix.pch' (normalmente você o encontrará no grupo 'arquivos de suporte', onde seu arquivo main.m está localizado
2) adicione essas 3 linhas no final do arquivo '.pch':
3) teste a diferença entre a sua versão de 'depuração' e 'lançamento'. Uma maneira de fazer isso é através do 'esquema de edição' -> 'executar nome do aplicativo' -> na guia 'informações', selecione usando a caixa suspensa entre depuração e lançamento. Na versão de lançamento, você não verá nenhuma saída NSLog no console de depuração!
Como tudo isso funciona?
em primeiro lugar, deve-se saber que um pré-processador é relativamente 'burro' e apenas atua como um 'substituto de texto' antes de o compilador ser chamado. Ele substitui qualquer coisa que você '#define' pelo que segue a
#define
declaração.O
(...)
significa 'qualquer coisa' entre os colchetes (). Lembre-se também;
do final. Isso não é estritamente necessário, pois o compilador irá otimizar isso, mas eu gosto de colocá-lo lá, pois é mais 'correto'. Depois de nosso,#define
não há 'nada', então o pré-processador irá substituí-lo por 'nada', e então jogará fora a linha completa, começando emNSLog...
até e incluindo o;
.as declarações de definição podem ser tornadas condicionais usando
#ifdef
(se definido) ou#ifndef
(se não definido)aqui escrevemos
#ifndef DEBUG
, o que significa 'se o símbolo DEBUG não está definido'. O#ifdef
ou#ifndef
precisa ser 'fechado' com#endif
O Xcode 5 define por padrão o símbolo 'DEBUG' para nós quando o modo de construção é 'DEBUG'. Em 'release' isso não está definido. você pode verificar isso nas configurações do projeto, guia 'Configurações de compilação' -> role para baixo até a seção 'Apple LLVM 5.0 - Pré-processamento' -> macros do pré-processador. Você verá que o símbolo 'DEBUG' não está definido para versões de lançamento!
finalmente, o arquivo .pch é criado pelo Xcode automaticamente e automaticamente incluído em cada arquivo de origem durante o tempo de compilação. Portanto, é como se você tivesse colocado
#define
tudo em cada um de seus arquivos de origem.fonte
NSLog
instruções, desconsiderando o que está dentro.NSLog
como uma declaração de não fazer nada, por exemplo, emif(AllCool) NSLog(@"Cool!Do Nothing!"); else...
vez disso,NSLog
if(AllCool) {NSLog(@"Cool!Do Nothing!");} else...
Quase todas as respostas acima sugerem uma solução, mas não explicam o problema. Fiz uma pesquisa no google e descobri o motivo. Aqui está minha resposta:
Sim, se você comentar o NSLog em sua versão de lançamento, o desempenho será melhor. Porque NSLog é muito lento. Por quê? NSLog fará duas coisas 1) escrever mensagens de log no Apple System Logging (ASL), 2) se o aplicativo for executado em xcode, ele gravará em stderr também.
O principal problema está no primeiro. Para obter um thread seguro, cada vez que o NSLog é chamado, ele abre uma conexão com o recurso ASL , envia uma mensagem e fecha a conexão. A operação de conexão é muito cara. Outro motivo é que o NSLog gasta algum tempo para obter o registro de data e hora.
Referência aqui .
fonte
Meu favorito pessoal é usar uma macro variável.
fonte
Além de todas as pessoas que sabiamente comentaram que não ligar
NSLog()
na produção é um pouco mais rápido, vou acrescentar que:Todas essas
NSLog()
strings de saída são visíveis para qualquer pessoa que baixe seu aplicativo da loja e o execute com o dispositivo conectado a um mac executando o Xcode (por meio da janela do Organizer).Dependendo das informações que você registra (e especialmente se seu aplicativo contata um servidor, faz autenticação, etc.), isso pode ser um sério problema de segurança .
fonte
print()
, mas provavelmente é.Dentro da configuração padrão atual do projeto no Xcode, a
NS_BLOCK_ASSERTIONS
macro será definida como 1 na versão de lançamento eDEBUG=1
na versão de depuração.Portanto, prefiro o método a seguir.
fonte
Sim, você deve desativá-lo. Especialmente se você estiver tentando maximizar a velocidade do seu código. O NSLogging da esquerda e da direita polui o log do sistema que outros desenvolvedores podem estar tentando vasculhar e pode ter um grande impacto no código crítico de velocidade (dentro de loops, etc.) Eu deixei acidentalmente algumas mensagens de log em uma função recursiva uma vez e conseguiu lançar uma atualização com um "aumento de velocidade de 30%!" algumas semanas depois ... ;-)
fonte
Todas boas respostas, mas aqui está outro pequeno truque que você pode considerar usar, principalmente nas fases de desenvolvimento / teste do seu aplicativo.
Também pode ser útil para o código de lançamento do aplicativo, se você quiser apenas desligar SEU código de depuração, e não mensagens que podem indicar problemas fora do controle direto do seu código.
O truque:
Você pode desativar o NSLog por arquivo .m simplesmente incluindo a linha a seguir na parte superior do arquivo .m :
( NOTA: NÃO coloque este arquivo .h, apenas o arquivo .m! )
Isso apenas faz com que o compilador avalie
NSLog()
expandindo a macro do pré-processador. A macro não faz nada além de remover os argumentos.se quiser ligá-lo novamente, você sempre pode usar
Você poderia, por exemplo, apenas evitar chamadas para NSLog em torno de um determinado grupo de métodos fazendo algo como
fonte
NSLog é lento e não deve ser usado para compilações de lançamento. Uma macro simples como a abaixo irá desativá-la junto com quaisquer declarações que você possa ter que também devem ser desativadas. No caso menos comum em que você deseja NSLog em uma versão de lançamento, basta chamá-lo diretamente. Não se esqueça de adicionar "-DNDEBUG" às configurações de compilação de "outras sinalizações c".
fonte
no arquivo pch anote isso antes de #endif
fonte
que tal isso?
fonte
Isso aceitará os argumentos adicionais também .. Apenas o valor do parâmetro showDebugLogs para true ou false, conforme sua necessidade
fonte
Dlog
função.