Mais d'où vient cette entrée dans le log?

&Petite astuce du jour: je ne sais pas si quand vous développez vous mettez des NSLog partout puis une fois "l'étape" terminée, vous perdez beaucoup de temps à  les rechercher pour les supprimer. Ou bien tout simplement vous voulez  savoir d'où vient un NSLog, ce qui facilite les éventuels débuggages.

Voici une petite astuce qui permettra de savoir où un log vient:

Définissez les macros suivantes (l'idéal étant de le faire dans un .h séparé qu'on peut ensuite importer partout où on veut):
[tt]#define OCLog(log) NSLog(@[%@ %s] \"%@\;"",[self class],sel_getName(_cmd),log)[/tt]
Les logs seront donc affichés sous la forme [Classe nomDeLaMéthode] "le message à  afficher".

Un autre avantage de cette méthode est qu'il est possible de mettre directement n'importe quel type d'objet comme argument (et pas uniquement des NSString comme le log normal).

Bon seul hic, comme c'est une macro, on ne peut plus mettre d'argument multiples pour avoir une expression de type "stringWithFormat". Il font donc définir d'autres macros en spécifiant le nombre d'argument pour la "stringWithFormat".
[tt]#define OCLog1(log,arg1) NSLog(@[%@ %s] \;%@\;"",[self class],_cmd,[NSString stringWithFormat:log,arg1])
#define OCLog2(log,arg1,arg2) NSLog(@[%@ %s] \"%@\;"",[self class],_cmd,[NSString stringWithFormat:log,arg1,arg2])
#define OCLog3(log,arg1,arg2,arg3) NSLog(@[%@ %s] %@",[self class],_cmd,[NSString stringWithFormat:log,arg1,arg2,arg3])[/tt]

Les OCLog1, OCLog2 et OCLog3 sont devenues "obselètes", voir plus bas, après la querelle des chiffoniers.

Donc au lieu de NSLog(@%@ %i",anObject,anInt), on utilise OCLog2(@%@ %i",anObject,anInt)

EDIT:

Au tour de OCLogN de devenir obselète, grâce à  l'information donnée ici, on peut tout faire avec la seule macro OCLog:
[tt]#define OCLog(log,...) NSLog(@[%@ %s] \"%@\;"",[self class],sel_getName(_cmd),log,##__VA_ARGS_)[/tt]

Réponses

  • aranaudaranaud Membre
    09:57 modifié #2
    Très intéressant.
    Merci.
  • ClicCoolClicCool Membre
    09:57 modifié #3
    Oui en effet, les macros sont pleinnes de possibilités.

    dans 1144871900:

    [tt]#define RPLog(log) NSLog(@[%@ %s] \"%@\;"",[self class],_cmd,log)[/tt]

    Mais pourquoi RPLog ?  ???
    C'est obligatoire ?  :P
    On peu pas plutot mettre CCLog ?  :kicking:

    Bon OK, je sors.  >:)
  • AliGatorAliGator Membre, Modérateur
    09:57 modifié #4
    dans 1163156807:

    Mais pourquoi RPLog ?  ???
    C'est obligatoire ?  :P
    On peu pas plutot mettre CCLog ?  :kicking:

    Bon OK, je sors.  >:)
    Tu voulais dire HBLog j'imagine. Mais moi je vote pour AliLog :P
  • mars 2007 modifié #5
    Tiens, puisqu'on parle de cette astuce, j'ai appris récemment dans ma chasse récente aux macros (ou pêche plutôt) qu'une macro pouvait prendre un nombre indéterminé d'arguments.

    Donc voici de quoi supprimer les OCLog1,OCLog2,... et les remplacer par une seule macro, que j'ai nommé OCLogN:
    [tt]#define OCLogN(log,...) NSLog(@[%@ %s] \"%@\;"",[self class],sel_getName(_cmd),[NSString stringWithFormat:log,__VA_ARGS__])[/tt]

    EDIT: remplacement de _cmd par sel_getName(_cmd)
  • AliGatorAliGator Membre, Modérateur
    09:57 modifié #6
    dans 1163178143:

    Tiens, puisqu'on parle de cette astuce, j'ai appris récemment dans ma chasse récente aux macros (ou pêche plutôt) qu'une macro pouvait prendre un nombre indéterminé d'arguments.

    Donc voici de quoi supprimer les OCLog1,OCLog2,... et les remplacer par une seule macro, que j'ai nommé OCLogN:
    [tt]#define OCLogN(log,...) NSLog(@[%@ %s] \"%@\;"",[self class],_cmd,[NSString stringWithFormat:log,__VA_ARGS__])[/tt]

    Ah je connaissais pas ce coup là  (appliquer le principe des va_args aux macros avec cette notation spécifique). C'est bon à  prendre :)

    Au passage du coup ja'i fait une recherche google sur ce __VA_ARGS__ et je suis tombé sur la doc de gcc sur les macros qui peux nous apprendre 2 ou 3 astuces :c'est là , chapitre 3.6 pour le fameux __VA_ARGS__  ;)

    On en apprend tous les jours  :o
  • aranaudaranaud Membre
    09:57 modifié #7
    Est que le nombre d'élement variable est limité seulment pour les macro ou est qui peut-être utilisé n'importe où dans le code ?
  • ClicCoolClicCool Membre
    09:57 modifié #8
    Pas de doutes Renaud tu m'as convaincu qu'il fallait que je creuse plus les macros :)

    dans 1163178918:

    Au passage du coup ja'i fait une recherche google sur ce __VA_ARGS__ et je suis tombé sur la doc de gcc sur les macros qui peux nous apprendre 2 ou 3 astuces :c'est là , chapitre 3.6 pour le fameux __VA_ARGS__  ;)

    On en apprend tous les jours  :o

    Purée de la bonne Mère !
    Exactement ce que je cherchais depuis 2 jours !!
    Merci Ali
  • AliGatorAliGator Membre, Modérateur
    09:57 modifié #9
    dans 1163179155:
    Est que le nombre d'élement variable est limité seulment pour les macro ou est qui peut-être utilisé n'importe où dans le code ?
    Heu attention à  ne pas confondre ce qui existe au niveau des macros et ce qui est compilé.
    Les macros sont remplacés par le préprocesseur. Les macros ce ne sont en gros que des remplacement de texte. aucune vérification de syntaxe ni quoi que ce soit, ce ne sont pas les mêmes mécanismes car pas la même étape (traitées AVANT la compilation).

    Pour faire des fonctions avec un nombre variable d'argument (comme NSLog, stringWithFormat, ...), c'est assez simple en C :
    maFonction(int firstArg, ...)<br />{<br />&nbsp; va_list args;<br />&nbsp; va_start(args, firstArg);<br /><br />&nbsp; //va_arg(args, &lt;type argument à  récupérer&gt;);<br />&nbsp; double secondArg = va_arg(args, double);<br />&nbsp; int thirdArg = va_arg(args, int);<br />&nbsp; // etc...<br /><br />&nbsp; va_end(args);<br />}
    
    La syntaxe est assez simple donc (il faut inclure <stdarg.h> pour avoir les fonctions va_*), il y a juste obligation de fournir un paramètre fixe (souvent on passe un entier auquel on passe le nombre d'arguments lors de l'appel, par exemple [tt]maFonction(3,"premier", "deuxième","troisième");[/tt])

    Après il suffit d'adapter pour l'Ojective-C, je n'ai jamais appliqué ça à  l'OC mais comme ce n'est qu'une surcouche du C, le principe est précisément le même (à  moins que Cocoa ne fournisse un wrapper pour récupérer les arguments pour faire plus propre à  la limite).

    En tout cas à  ne pas confondre avec le fonctionnement en macros (pour lequel ils ont repris le nom de "va_arg" pour __VA_ARGS__ uniquement j'imagine par similitude de la fonctionnalité, mais pas du mécanisme)
    dans 1163180430:
    Purée de la bonne Mère !
    Exactement ce que je cherchais depuis 2 jours !!
    Merci Ali
    Héhé, google est mon ami ;)
  • 09:57 modifié #10
    dans 1163187527:

    Après il suffit d'adapter pour l'Ojective-C, je n'ai jamais appliqué ça à  l'OC mais comme ce n'est qu'une surcouche du C, le principe est précisément le même (à  moins que Cocoa ne fournisse un wrapper pour récupérer les arguments pour faire plus propre à  la limite).

    Rien de prévu en OC pour ça, pour la bonne et simple raison que pour respecter la logique "objet", il est plus cohérent de passer une collection en argument (tableau, ensemble ou dico). Passer une collection en argument est aussi plus sûr (il n'y a pas le problème du comptage du nombre d'arguments, par exemple).
  • aranaudaranaud Membre
    09:57 modifié #11
    Merci à  vous deux pour ces éclaircissements.
  • mars 2007 modifié #12
    Le petit rappel fait par Chacha de cette astuce m'a fait relever une petite erreur, due à  mon ignorance de l'époque: dans cette ligne

    [tt]NSLog(@[%@ %s] \"%@\;"",[self class],_cmd,log)[/tt]

    se cache une petite erreur, qui ne causera pas de problème à  l'exécution sur un 32bit (mais ça ne l'empêche pas d'être mal écrite) et qui risque d'en causer sur un appli compilée pour 64bit (pas pu vérifier, mais je fais confiance à  la doc). Il faut donc apporter les corrections suivantes:

    [tt]NSLog(@[%@ %s] \"%@\;"",[self class],sel_getName(_cmd),log)[/tt]

    (elles ont été faites dans les messages ci-dessus)
  • avril 2008 modifié #13
    Une petite errur : il manque un _ à  __VA_ARGS_ ;)

    Je me suis permis de la modifier en:
    <br /> #define ErrorLog(log,...) NSLog([NSString stringWithFormat:@&quot;Error: %@ - %s - &#092;&quot;%@&#092;&quot;&quot;,self,sel_getName(_cmd),log],##__VA_ARGS__);<br />
    
Connectez-vous ou Inscrivez-vous pour répondre.