Foi-me dito isso algumas vezes neste mesmo site, mas eu queria ter certeza de que esse é realmente o caso.
Eu esperava poder espalhar chamadas de função do NSLog por todo o meu código e que o Xcode / gcc removesse essas chamadas automaticamente ao criar minhas compilações de Liberação / Distribuição.
Devo evitar usar isso? Em caso afirmativo, quais alternativas são mais comuns entre programadores experientes em Objective-C?
iphone
objective-c
nslog
jpm
fonte
fonte
Respostas:
Macros de pré-processador são realmente ótimas para depuração. Não há nada errado com o NSLog (), mas é simples definir sua própria função de log com melhor funcionalidade. Aqui está o que eu uso, ele inclui o nome do arquivo e o número da linha para facilitar o rastreamento de instruções de log.
Achei mais fácil colocar essa declaração inteira no cabeçalho do prefixo do que em seu próprio arquivo. Você poderia, se quisesse, criar um sistema de log mais complicado, fazendo o DebugLog interagir com objetos Objective-C normais. Por exemplo, você pode ter uma classe de log que grava em seu próprio arquivo de log (ou banco de dados) e inclui um argumento de 'prioridade' que você pode definir em tempo de execução, para que as mensagens de depuração não sejam mostradas na versão de lançamento, mas as mensagens de erro ( se você fez isso, poderá criar DebugLog (), WarningLog () e assim por diante).
Ah, lembre-se de que
#define DEBUG_MODE
pode ser reutilizado em diferentes locais do seu aplicativo. Por exemplo, no meu aplicativo, eu o uso para desativar as verificações de chave de licença e permitir que o aplicativo seja executado somente antes de uma determinada data. Isso me permite distribuir uma cópia beta totalmente funcional e com tempo limitado, com o mínimo esforço da minha parte.fonte
Coloque estas 3 linhas no final do arquivo -prefix.pch:
Você não precisa definir nada no seu projeto, porque
DEBUG
é definido na configuração de compilação por padrão quando você cria o seu projeto.fonte
As chamadas do NSLog podem ser deixadas no código de produção, mas só devem existir para casos realmente excepcionais ou para as informações desejadas que serão registradas no log do sistema.
Os aplicativos que desarrumam o log do sistema são irritantes e parecem não profissionais.
fonte
Não posso comentar a resposta de Marc Charbonneau , por isso vou postar isso como resposta.
Além de adicionar a macro ao cabeçalho pré-compilado, você pode usar as configurações de criação do Target para controlar a definição (ou falta de definição) do
DEBUG_MODE
.Se você selecionar a configuração ativa " Debug ",
DEBUG_MODE
ela será definida e a macro será expandida para a totalidadeNSLog
definição .Selecionar a configuração ativa " Liberar " não definirá
DEBUG_MODE
e seuNSLog
ging será omitido na compilação do release.Passos:
GCC_PREPROCESSOR_DEFINITIONS
)DEBUG_MODE=1
DEBUG_MODE
não está definido emGCC_PREPROCESSOR_DEFINITIONS
se você omitir o caractere '=' na definição, você receberá um erro do pré-processador
Além disso, cole este comentário (mostrado abaixo) acima da definição da macro para lembrá-lo de onde
DEBUG_MACRO
vem a definição;)fonte
DEBUG_MODE
eDEBUG_MACRO
não são convencionais. Eu encontrei apenas uma referênciaDEBUG_MACRO
no site da apple ( opensource.apple.com/source/gm4/gm4-15/src/m4.h?txt ). Talvez o mais padrãoDEBUG
eNDEBUG
seria melhores escolhas?NDEBUG
é especificado por Posix; whileDEBUG
é usado por convenção.EDIT: O método publicado por Marc Charbonneau , e trouxe à minha atenção por sho , é muito melhor que este.
Excluí a parte da minha resposta que sugeria o uso de uma função vazia para desativar o log quando o modo de depuração está desativado. A parte que lida com a configuração de uma macro de pré-processador automático ainda é relevante, portanto permanece. Também editei o nome da macro do pré-processador para que ela se encaixe melhor na resposta de Marc Charbonneau.
Para alcançar o comportamento automático (e esperado) no Xcode:
Nas configurações do projeto, vá para a guia "Build" e selecione a configuração "Debug". Localize a seção "Macros de pré-processador" e adicione uma macro denominada
DEBUG_MODE
....
EDIT: consulte a resposta de Marc Charbonneau para a maneira correta de ativar e desativar o log com a
DEBUG_MODE
macro.fonte
Eu concordo com Matthew. Não há nada errado com o NSLog no código de produção. De fato, pode ser útil para o usuário. Dito isto, se o único motivo pelo qual você está usando o NSLog é ajudar na depuração, sim, isso deve ser removido antes do lançamento.
Além disso, como você marcou isso como uma pergunta do iPhone, o NSLog usa recursos, algo que o iPhone tem muito pouco. Se você está registrando algo no iPhone, isso reduz o tempo do processador do seu aplicativo. Use com sabedoria.
fonte
A verdade simples é que o NSLog é simplesmente lento.
Mas por que? Para responder a essa pergunta, vamos descobrir o que o NSLog faz e, em seguida, como ele faz.
O que o NSLog faz exatamente?
O NSLog faz 2 coisas:
Ele grava mensagens de log no recurso Apple System Logging (asl). Isso permite que as mensagens de log sejam exibidas no Console.app. Ele também verifica se o fluxo stderr do aplicativo está indo para um terminal (como quando o aplicativo está sendo executado via Xcode). Nesse caso, ele grava a mensagem de log no stderr (para que apareça no console do Xcode).
Escrever para STDERR não parece difícil. Isso pode ser feito com fprintf e a referência do descritor de arquivo stderr. Mas e quanto a asl?
A melhor documentação que eu encontrei sobre o ASL é uma postagem de blog de 10 partes de Peter Hosey: link
Sem entrar em muitos detalhes, o destaque (no que diz respeito ao desempenho) é o seguinte:
Para enviar uma mensagem de log para o recurso ASL, você basicamente abre uma conexão do cliente com o daemon ASL e envia a mensagem. MAS - cada thread deve usar uma conexão de cliente separada. Portanto, para ser seguro para threads, toda vez que o NSLog é chamado, ele abre uma nova conexão de cliente ASL, envia a mensagem e fecha a conexão.
Recursos podem ser encontrados aqui e aqui .
fonte
Conforme observado em outras respostas, você pode usar um #define para alterar se o NSLog é usado ou não no momento da compilação.
No entanto, uma maneira mais flexível é usar uma biblioteca de registro como o Cocoa Lumberjack, que permite alterar se algo também é registrado em tempo de execução.
No seu código, substitua o NSLog por DDLogVerbose ou DDLogError etc, adicione um #import para as definições de macro etc e configure os registradores, geralmente no método applicationDidFinishLaunching.
Para ter o mesmo efeito que o NSLog, o código de configuração é
fonte
Do ponto de vista da segurança, depende do que está sendo registrado. Se
NSLog
(ou outros registradores) estiverem gravando informações confidenciais, você deverá remover o registrador no código de produção.Do ponto de vista da auditoria, o auditor não deseja examinar cada uso de
NSLog
para garantir que não registre informações confidenciais. Ele simplesmente diz para você remover o logger.Eu trabalho com os dois grupos. Auditamos código, escrevemos os guias de codificação, etc. Nosso guia exige que o registro seja desativado no código de produção. Portanto, as equipes internas sabem que não devem tentar;)
Também rejeitaremos um aplicativo externo que faça logon na produção, porque não queremos aceitar o risco associado ao vazamento acidental de informações confidenciais. Não nos importamos com o que o desenvolvedor nos diz. Simplesmente não vale o nosso tempo para investigar.
E lembre-se, definimos 'sensível', e não o desenvolvedor;)
Também percebo um aplicativo que executa muitos logs como um aplicativo pronto para implodir. Há uma razão pela qual tanto o log é realizado / necessário, e geralmente não é estável. É lá em cima com threads 'watchdog' que reiniciam os serviços travados.
Se você nunca passou por uma revisão da Security Architecture (SecArch), esses são os tipos de coisas que analisamos.
fonte
Você não deve ser desnecessariamente detalhado com printf ou NSLog no código de liberação. Tente fazer apenas um printf ou NSLog se o aplicativo tiver algo ruim, ou seja, um erro irrecuperável.
fonte
Lembre-se de que o NSLogs pode diminuir a velocidade da interface do usuário / thread principal. É melhor removê-los das versões de lançamento, a menos que seja absolutamente necessário.
fonte
Eu recomendo usar o TestFlight para log (gratuito). O método deles substituirá o NSLog (usando uma macro) e permitirá que você ative / desative o log no servidor deles, o log do Apple System e o STDERR, para todas as chamadas existentes para o NSLog. O bom disso é que você ainda pode revisar suas mensagens de log para aplicativos implantados em testadores e aplicativos implantados na App Store, sem que os logs apareçam no log do sistema do usuário. O melhor de dois mundos.
fonte