BLOG
FILTROS
TAGS MAIS USADAS
Dicas para ajudar a depurar o código em Objective-C
-
AUTOR
Afonso Junior
TAGs desenvolvimento, iphone sdk
1 COMENTÁRIO-
Tweet
Por mais que o seu projeto seja bem testado, e que você tenha se esforçado ao máximo para não ter gambiarras no código-fonte, inevitavelmente haverá momentos em que você precisará depurar o código em busca de erros.
Para muitos, é nesse momento que começa o desespero. Embora alguns achem o Xcode a quinta maravilha do mundo como IDE, ela ainda peca um pouco na hora de dar suporte ao desenvolvedor para achar erros.
Nesse post recolhemos algumas dicas úteis que utilizamos em nossos projetos. Vale lembrar que a maioria delas já está disponível na internet, o que fizemos foi juntá-los aqui.
Melhorias no Log
Para aqueles que usam e abusam do NSLog, devem sempre ter em mente que ele sai no console do aparelho. Ou seja, vai que você esquece de apagar aquele NSLog que escreve algo que o usuário não deveria saber. Aí, basta que o usuário tenha o Xcode ou o iPhone Configuration Utility, e - que beleza! - está lá a informação que voce não deveria mostrar.

Outro ponto que alguns desenvolvedores reclamam é de ter sempre que usar texto formatado no NSLog. Os que vieram de Java provavelmente sentem saudades do System.out.println(), que, embora verborrágico, ao menos permitia colocar lá o objeto que quisesse, e funcionava.
Por conta disso, criamos algumas diretivas no Prefix.pch para facilitar nossa vida. Veja o código a seguir:
#ifdef DISTRIBUTION
#define myLog(format,...)
#define myLogD(obj)
#define myLogI(myint)
#define myLogF(myfloat)
#define MARK
#else
#define myLog(format, ...) NSLog(@"%s:%@", __PRETTY_FUNCTION__,[NSString stringWithFormat:format, ## __VA_ARGS__]);
#define myLogD(obj) NSLog(@"%s:%@", __PRETTY_FUNCTION__,[NSString stringWithFormat:@"%@", obj]);
#define myLogI(myint) NSLog(@"%s:%@", __PRETTY_FUNCTION__,[NSString stringWithFormat:@"%d", myint]);
#define myLogF(myfloat) NSLog(@"%s:%@", __PRETTY_FUNCTION__,[NSString stringWithFormat:@"%f", myfloat]);
#define MARK myLog(@"");
#endif
A gente criou o myLog(), que substitui o NSLog do Objective-C. Perceba que o #ifdef inicial distingue o comportamento do método para distribuição dos outros modos. Em distribuição, o myLog() não faz nada. Já nas outras configurações ele joga no output o resultado do método NSLog.
Percebeu que ele tem um __PRETTY_FUNCTION__ no método? Pois é, isso serve para imprimir também o nome do método de onde o myLog() foi chamado. Mais uma facilidade que ajuda muito na hora de ver o valor no output.
Depois disso, temos mais três métodos:
#define myLogD(obj) NSLog(@"%s:%@", __PRETTY_FUNCTION__,[NSString stringWithFormat:@"%@", obj]);
#define myLogI(myint) NSLog(@"%s:%@", __PRETTY_FUNCTION__,[NSString stringWithFormat:@"%d", myint]);
#define myLogF(myfloat) NSLog(@"%s:%@", __PRETTY_FUNCTION__,[NSString stringWithFormat:@"%f", myfloat]);
O primeiro, o myLogD(), serve para exibir a descrição de um objeto. Digamos que você tenha um objeto cliente. Basta utilizar o método dessa forma:
myLogD(cliente);
e ele imprime na tela a descrição dele. O segundo e o terceiro servem para variáveis inteiras e de ponto flutuante.
E tem o último método, o MARK. Lembra das vezes em que você teve que depurar, e queria saber se um método era chamado na execução do programa? Em tempos antigos você utilizaria NSLog(@"passei no método conectar()"), ou algo semelhante. Pois bem, com o MARK, basta escrever MARK no código, e ele imprime o nome do método na saída. Simples, não?
O temido EXC_BAD_ACCESS
De todos os erros genéricos que o Objective-C pode te mostrar, um dos piores é o EXC_BAD_ACCESS. O EXC_BAD_ACCESS é lançado quando o programa tenta enviar uma mensagem (por exemplo, a chamada de um método) para um objeto que já foi liberado (released). Na maioria das vezes, quando o erro é detectado, a pilha de processos onde o objeto estava já se foi, o que dificulta descobrir onde o erro realmente aconteceu.
Mas há uma solução que na maioria dos casos consegue mapear qual objeto foi liberado: basta utilizar a variável de ambiente NSZombieEnabled. Com ela, o Objective-C deixa alocado na memória um objeto dummy, guardando a referência. Quando acontece o EXC_BAD_ACCESS, ele retorna o objeto e a mensagem que foi enviada para ele.
Para habilitar essa variável é bem simples: na seção 'Executables', clique duas vezes no executável do seu projeto. Na aba 'Arguments', na seção 'Variables to be set in the enviroment', adicione a variável NSZombieEnabled, dando o valor YES para ela. Para habilitar, basta marcar o check a esquerda.

Vale chamar a atenção para um detalhe: como o NSZombieEnabled é um recurso que guarda na memória os objetos que foram liberados, tenha em mente que ela é um auxílio para testes, e, portanto, não deixe essa variável habilitada. Aconteceu o EXC_BAD_ACCESS, utilize o NSZombieEnabled, descubra onde foi o problema e desabilite, para não correr o risco de seu programa utilizar mais memória do que ele realmente necessita.
Milhares de Breakpoint
Imagine o cenário: você testou o que queria testar, utilizou centenas de breakpoints. Agora quer testar outra coisa, e quer tirar todos os breakpoints que não servem mais? Algumas pessoas não percebem, mas o Xcode permite que você os retire de maneira mais fácil. Na seção 'Groups and files', a esquerda, um dos últimos itens é o de Breakpoints. Lá você pode retirar todos os breakpoints de uma vez, basta selecionar e excluir.

Enfim, por hora é só. Caso tenha alguma dúvida, ou sugestão, é só colocar nos comentários. Abraço a todos.
1 COMENTÁRIO
-
Gutenberg Neto 11/02/2011, 12:08
Ótimas dicas! Zombies, em especial, eu considero fundamentais para quem trabalha com Objective-C.





+55 21 3553-1898