Vos macros les plus utiles

2»

Réponses

  • Je l'avais lu dans une doc signées Apple d'ailleurs.. J'y vais fort en disant qu'il ne faut JAMAIS le faire. Il était plutôt écrit que c'est à  éviter.
  • psychoh13psychoh13 Mothership Developer Membre
    'ldesroziers' a écrit:


    Normalement il ne faut jamais faire de == sur des flottants. Il suffira de rajouter && < nouvelleHauteurDuProchainiPhone

    Mais à  mon avis on est tranquille un bon bout de temps image/tongue.png' class='bbc_emoticon' alt=':P' />




    Il ne faut jamais dire jamais, surtout quand c'est faux, ce qui est le cas ici, == marchera sur ce nombre, il n'y a aucun problème ici.



    http://www.mikeash.com/pyblog/friday-qa-2011-01-04-practical-floating-point.html
  • Cf mon message après où j'ai rectifié le "jamais", môssieur.
  • MistifiouMistifiou Membre
    octobre 2012 modifié #35
    'psychoh13' a écrit:


    Une autre technique qui n'utilise pas les pragma c'est d'utiliser des commentaires comme ceci:
    // TODO: something<br />
    // FIXME: something<br />
    // MARK: something<br />
    




    L'inconvénient c'est que tu n'as pas de warning pour ça, mais l'avantage c'est qu'il s'affiche dans le menu des symboles de ton fichier donc tu peux y aller directement.




    Perso j'ai implémenté un petit bout de code qui, lors de la compilation me remonte les //TODO: et //FIXME:.



    Pour info, sur l'écran du projet, il faut se rendre dans "Build Phases" (là  où on rajoute les libraries), puis cliquer sur "Add build phase" et choisir "run script".



    juste en dessous du champ "Shell", rentrer le code suivant :


    <br />
    KEYWORDS=&quot;TODO:|FIXME:|&quot;<br />
    find &quot;&#036;{SRCROOT}&quot; \( -name &quot;*.h&quot; -r -name &quot;*.m&quot; \) -print0 | xargs -0 egrep --with-filename --line-number --only-matching &quot;(&#036;KEYWORDS).*\&#036;&quot; | perl -p -e &quot;s/(&#036;KEYWORDS)/ warning \&#036;1/&quot;<br />
    




    et voila ! tout commentaire qui commence par TODO: ou FIXME: est automatiquement mis en warning !



    Concernant les macros, je n'en ai pas implémenté personellement mais j'utilise beaucoup celle-ci qui permet de simuler des singleton en objective-c.


    <br />
    //<br />
    //  KSSingleton.h<br />
    //<br />
    //  Created by Florent Morin on 27/03/10.<br />
    //  Copyright 2010 Kaeli Soft.<br />
    //<br />
    //  http://www.kaelisoft.fr<br />
    //<br />
    <br />
    /*<br />
    * __ Integration __ (minimal)<br />
    *<br />
    * #import &quot;KSSingleton.h&quot;<br />
    *<br />
    * @interface MySingleton {<br />
    * ...<br />
    * }<br />
    *<br />
    * KS_SINGLETON_INTERFACE(MySingleton)<br />
    *<br />
    * ...<br />
    *<br />
    * @end<br />
    *<br />
    *<br />
    * @implementation MySingleton<br />
    *<br />
    * KS_SINGLETON_IMPLEMENTATION(MySingleton)<br />
    *<br />
    * ...<br />
    *<br />
    * @end<br />
    *<br />
    */<br />
    /*<br />
    * __ Initialization __ (optional)<br />
    *<br />
    * @interface MySingleton {<br />
    * }<br />
    *<br />
    * ...<br />
    *<br />
    * - (void)initialization;<br />
    *<br />
    * @ end<br />
    *<br />
    * @implementation MySingleton<br />
    *<br />
    * - (void)initialization {<br />
    * }<br />
    *<br />
    * @end<br />
    *<br />
    */<br />
    /*<br />
    * __ Usage __<br />
    *<br />
    * MySingleton *s = [MySingleton sharedMySingleton];<br />
    *<br />
    */<br />
    #define KS_SINGLETON_INTERFACE(singletonclass) \<br />
    + (singletonclass *)shared##singletonclass;<br />
    #define KS_SINGLETON_IMPLEMENTATION(singletonclass) \<br />
    \<br />
    static singletonclass *shared##singletonclass = nil; \<br />
    \<br />
    + (singletonclass *)shared##singletonclass { \<br />
    if (shared##singletonclass == nil) { \<br />
    shared##singletonclass = [[super allocWithZone:NULL] init]; \<br />
    if ([shared##singletonclass respondsToSelector:@selector(initialization)]) { \<br />
    [shared##singletonclass performSelector:@selector(initialization)]; \<br />
    } \<br />
    } \<br />
    \<br />
    return shared##singletonclass; \<br />
    } \<br />
    \<br />
    + (id)allocWithZone:(NSZone *)zone { \<br />
    return [[self shared##singletonclass] retain]; \<br />
    } \<br />
    \<br />
    - (id)copyWithZone:(NSZone *)zone { \<br />
    return self; \<br />
    } \<br />
    \<br />
    
  • AliGatorAliGator Membre, Modérateur
    octobre 2012 modifié #36
    Pas bête le script pour convertir les TODO: en warnings image/smile.png' class='bbc_emoticon' alt=':)' />



    Sinon moi depuis pas mal de temps maintenant pour l'implémentation du singleton, je n'utilise plus du tout la façon de faire présente dans la doc Apple (de toute façon tout le monde est d'accord pour dire qu'elle n'est plus d'actualité, y compris les devs Apple eux-même à  la WWDC).



    J'utilise à  la place la version GCD, plus courte, thread-safe, compatible ARC, et tout :


    @implementation MyService<br />
    +(MyService*)sharedInstance<br />
    {<br />
    	static MyService* sharedInstance;<br />
    	static dispatch_once_t once;<br />
    	dispatch_once(&amp;once, ^{ sharedInstance = [[MyService alloc] init]; });<br />
    	return sharedInstance;<br />
    }<br />
    @end
    
    C'est court, suffisant, et en plus c'est facile de faire un Code Clipping (sélectionner + glisser dans la palette de Xcode des Text Clipping) et lui attribuer un contexte et un mot d'autocompletion.



    PS : Je ne comprend pas l'intérêt de ta méthode optionnelle "initialisation" (dont tu testes du coup la présence et tout), quel avantage ça apporte par rapport à  la surcharge du "init" habituel ?
  • MistifiouMistifiou Membre
    octobre 2012 modifié #37
    @Ali : j'étais pas au courant que cette version, du coup j'vais essayer de changer la macro pour qu'elle respecte la méthode GCD image/smile.png' class='bbc_emoticon' alt=':)' />



    Comme dit plus haut ce n'est pas de moi, et pour être franc jusqu'à  la lecture de cet article je n'avais aucune idée de l'existance des macros.



    Je suis pas très lecteur, donc je teste un peu tout et fouille sur internet des solutions toutes faites sur lesquelles je m'appuis pour évoluer.
  • Deux petites remarques :

    - la macro KSSingleton n'est pas en OpenSource, elle est sous Copyright de Kaeli Soft,

    - implémenter seulement la nouvelle méthode +sharedInstance, même GCD et tout et tout, ne suffit pas en toute rigueur pour implémenter le Pattern Singleton : rien n'empêche de créer d'autres instances par +new.
  • psychoh13psychoh13 Mothership Developer Membre
    Empêcher la création d'autres instances, c'est-à -dire la différence entre singleton et multipleton, est inutile dans la majorité des cas, le pattern du multipleton utilisant GCD est largement suffisant. Mais bon en général je trouve qu'utiliser une instance globale directement est super moche parce que ça force les deux classes impliqués (le multipleton et la classe l'utilisant) à  travailler ensemble. Non pas que c'est forcément mauvais, mais les globales sont généralement à  éviter et des techniques plus propres existent dans la plupart des cas.



    Aussi, je tiens à  faire remarquer une chose à  propos du code posté par Mistifiou: l'implémentation n'empêche pas de passer par la méthode -init plusieurs fois, et ça peut être ennuyeux si tu utilises [[singleton alloc] init], certes tu auras la même instance mais le message init aura été envoyé deux fois au même objet...
  • 'AliGator' a écrit:


    Pas bête le script pour convertir les TODO: en warnings image/smile.png' class='bbc_emoticon' alt=':)' />



    Sinon moi depuis pas mal de temps maintenant pour l'implémentation du singleton, je n'utilise plus du tout la façon de faire présente dans la doc Apple (de toute façon tout le monde est d'accord pour dire qu'elle n'est plus d'actualité, y compris les devs Apple eux-même à  la WWDC).



    J'utilise à  la place la version GCD, plus courte, thread-safe, compatible ARC, et tout :


    @implementation MyService<br />
    +(MyService*)sharedInstance<br />
    {<br />
    	static MyService* sharedInstance;<br />
    	static dispatch_once_t once;<br />
    	dispatch_once(&amp;once, ^{ sharedInstance = [[MyService alloc] init]; });<br />
    	return sharedInstance;<br />
    }<br />
    @end
    
    C'est court, suffisant, et en plus c'est facile de faire un Code Clipping (sélectionner + glisser dans la palette de Xcode des Text Clipping) et lui attribuer un contexte et un mot d'autocompletion.



    PS : Je ne comprend pas l'intérêt de ta méthode optionnelle "initialisation" (dont tu testes du coup la présence et tout), quel avantage ça apporte par rapport à  la surcharge du "init" habituel ?




    Tiens, je serais curieux d'avoir une explication sur pourquoi la méthode GCD est mieux sur l'ancienne. Ici on se paye deux static pour que ça fonctionne, contre un seul dans l'ancien monde...



    Aujourd'hui, j'ai toujours tendance à  préférer l'ancien que je trouve plus efficace à  première vue...
  • christopheLchristopheL Membre
    octobre 2012 modifié #41
    au sujet des logs et des todos j'utilise ca qui remplace NSLog :





    [/size][/font][/color]<br />
    [color=#78492A][font=Menlo][size=2]#ifdef DEBUG[/size][/font][/color]<br />
    [color=#78492A][font=Menlo][size=2]#define CLLog( s, ... ) NSLog( @[color=#d12f1b]&quot;&lt;%p %@:(l%d)&gt; %@&quot;[/color], self, [[NSString stringWithUTF8String:__FILE__] lastPathComponent], __LINE__, [NSString stringWithFormat:(s), ##__VA_ARGS__] )[/size][/font][/color]<br />
    [color=#78492A][font=Menlo][size=2]#define CLTodo( s, ...) NSLog( @[color=#d12f1b]&quot;#TODO : &lt; %@:(l%d)&gt; %@&quot;[/color], [[NSString stringWithUTF8String:__FILE__] lastPathComponent], __LINE__, [NSString stringWithFormat:(s), ##__VA_ARGS__] )[/size][/font][/color]<br />
    [color=#78492A][font=Menlo][size=2]#else[/size][/font][/color]<br />
    [color=#78492A][font=Menlo][size=2]#define CLLog( s, ... )[/size][/font][/color]<br />
    [color=#78492A][font=Menlo][size=2]#define CLTodo( s, ...)[/size][/font][/color]<br />
    [color=#78492A][font=Menlo][size=2]#endif[/size][/font][/color]<br />
    




    Ca a notamment l'avantage d'éviter d'oublier de retirer/commenter les NSLog lorsqu'on fait une archive. J'aime beaucoup les warnings d'ali et je pense que pour mes todo je ferai comme lui dorénavant car cela tient plus du commentaire que du log.



    Sinon j'aime bien pouvoir passer une couleur hexa :





    [/size][/font][/color]<br />
    [color=#78492A][font=Menlo][size=2]#define UIColorFromRGB(rgbValue) [UIColor colorWithRed:((float)((rgbValue &amp; [color=#272ad8]0xFF0000[/color]) &gt;&gt; [color=#272ad8]16[/color]))/[color=#272ad8]255.0[/color] green:((float)((rgbValue &amp; [color=#272ad8]0xFF00[/color]) &gt;&gt; [color=#272ad8]8[/color]))/[color=#272ad8]255.0[/color] blue:((float)(rgbValue &amp; [color=#272ad8]0xFF[/color]))/[color=#272ad8]255.0[/color] alpha:[color=#272ad8]1.0[/color]][/size][/font][/color]<br />
    <br />
    <br />
    [color=#000000][[/color][color=#4f8187]monlabel[/color][color=#000000] [/color][color=#3d1d81]setTextColor[/color][color=#000000]:[/color]UIColorFromRGB[color=#000000]([/color][color=#272ad8]0x555555[/color][color=#000000])];[/color]<br />
    <br />
    
  • AliGatorAliGator Membre, Modérateur
    En effet en toute rigueur ce n'est pas un singleton j'ai même failli préciser ce détail dans mon post. Mais en pratique comme le dit psychoh13 le but est surtout d'avoir une sharedInstance commune accessible partout plutôt que réellement interdire la multi-allocation.



    De plus il est à  ma connaissance impossible d'implementer un réel singleton quand on activé ARC, l'utilisation et la surcharge de alloc & ci étant proscrite par le compilateur. Notez que même en MRC la méthode allocWithZone est obsolète, les NSZone ayant été abandonnées par Apple.



    Tout ceci ne change pas le fait évidemment qu'il ne faut utiliser ce pattern que s'il a vraiment un sens dans votre contexte et ne pas faire un multipleton pour tout et n'importe quoi, ça doit se justifier. Pour ma part ma seule utilisation quasiment de ce pattern est pour implémenter des services (façade de WebService en particulier).



    Yoann : avantage du code GCD par rapport à  l'ancien : c'est compatible ARC, c'est thread-safe grâce au dispatch_once, et même si ça utilise 2 static ça me choque moins car cette static est à  l'intérieur de la méthode +sharedInstance donc aucune autre méthode ne va y accéder, ça me choque moins ce genre de static que d'avoir une static "globale" accessible dans tout le fichier sans protection aucune.
  • AliGatorAliGator Membre, Modérateur
    En effet en toute rigueur ce n'est pas un singleton j'ai même failli préciser ce détail dans mon post. Mais en pratique comme le dit psychoh13 le but est surtout d'avoir une sharedInstance commune accessible partout plutôt que réellement interdire la multi-allocation.



    De plus il est à  ma connaissance impossible d'implementer un réel singleton quand on activé ARC, l'utilisation et la surcharge de alloc & ci étant proscrite par le compilateur. Notez que même en MRC la méthode allocWithZone est obsolète, les NSZone ayant été abandonnées par Apple.



    Tout ceci ne change pas le fait évidemment qu'il ne faut utiliser ce pattern que s'il a vraiment un sens dans votre contexte et ne pas faire un multipleton pour tout et n'importe quoi, ça doit se justifier. Pour ma part ma seule utilisation quasiment de ce pattern est pour implémenter des services (façade de WebService en particulier).



    Yoann : avantage du code GCD par rapport à  l'ancien : c'est compatible ARC, c'est thread-safe grâce au dispatch_once, et même si ça utilise 2 static ça me choque moins car cette static est à  l'intérieur de la méthode +sharedInstance donc aucune autre méthode ne va y accéder, ça me choque moins ce genre de static que d'avoir une static "globale" accessible dans tout le fichier sans protection aucune.
  • LarmeLarme Membre
    mai 2013 modifié #44

    Plop...


    Je reviens sur ce topic que je trouve très intéressant...


    Moi et les macros, ça fait deux, voire trois...


     


    Une idée que j'ai en tête, c'est de faire un truc de ce genre :


    Niveau de debug : Paramètre à  setter.

    Niveau0 0, Niveau1 1, etc.


    if (niveau de debug >= i ) { NSLog(@Blablabla);}


    Là , tel quel, je ferais ainsi :

    #define NIVEAUDEBUG 2 //À modifier avec le Build&Run en fonction de ce que je veux

    enum( debug0, debug1,debug2,debug3,debug4,debug5};

    Devant chaque NSLog : if (NIVEAUDEBUG > debugX) {NSLog(@rngren);}

    Avec peut-être une surchage de NSLog, pour inclure directement cette boucle if, de manière à  juste écrire NSLog(niveauDeDebugPropreACeNSLog, " NSLog classique ");


     


    C'est débile comme implémentation ? Pour l'instant, je ne m'intéresse pas à  ce que les NSLogs soient propre à  ce qui touche la connexion ou autre...


  • JegnuXJegnuX Membre
    mai 2013 modifié #45

    Voici



    #define NSLog(debugX, fmt, ...) if (debugX <= NIVEAUDEBUG) {NSLog(fmt, ##__VA_ARGS__);}

    // Avec un debug de 2 :

    #define NIVEAUDEBUG 2
    ...
    NSLog(0, @test : %i, 0);
    NSLog(1, @test : %i, 1);
    NSLog(2, @test : %i, 2);
    NSLog(3, @test : %i, 3);
    NSLog(4, @test : %i, 4);
    NSLog(5, @test : %i, 5);

    // Resultats :

    2013-05-15 15:32:47.358 Untitled[17953:707] test : 0
    2013-05-15 15:32:47.360 Untitled[17953:707] test : 1
    2013-05-15 15:32:47.360 Untitled[17953:707] test : 2

    À voir si c'est bien la condition que tu souhaites.


     


    Sinon par sur un vrai gestionnaire de log comme CocoaLumberjackNSLogger ou SOLogger


  • AliGatorAliGator Membre, Modérateur
    Mes macros à  utiliser avec CocoaLumberJack pour utiliser des "modules" de log :

    typedef struct {
    const char* displayName;
    const int logLevel;
    } _LogModule_t;

    #define _LogModuleFormat(module,frmt) @[%s] frmt, module.displayName
    #define NFLogError(module, frmt, ...) LOG_OBJC_MAYBE(LOG_ASYNC_ERROR, module.logLevel, LOG_FLAG_ERROR, 0, _LogModuleFormat(module,frmt), ##__VA_ARGS__)
    #define NFLogWarn(module, frmt, ...) LOG_OBJC_MAYBE(LOG_ASYNC_WARN, module.logLevel, LOG_FLAG_WARN, 0, _LogModuleFormat(module,frmt), ##__VA_ARGS__)
    #define NFLogInfo(module, frmt, ...) LOG_OBJC_MAYBE(LOG_ASYNC_INFO, module.logLevel, LOG_FLAG_INFO, 0, _LogModuleFormat(module,frmt), ##__VA_ARGS__)
    #define NFLogVerbose(module, frmt, ...) LOG_OBJC_MAYBE(LOG_ASYNC_VERBOSE, module.logLevel, LOG_FLAG_VERBOSE, 0, _LogModuleFormat(module,frmt), ##__VA_ARGS__)
    Pour chaque nouveau projet que je crée, j'importe mon header qui contient ces définitions, je définis à  côté les LogModules qui me semblent pertinents pour mon application en fonction de comment je veux catégoriser mes logs et le level que je veux leur donner, et basta.

    Pour définir les LogModules, je peux définir plein de "_LogModule_t const" mais je préfère faire une "const struct" qui les regroupe tous, comme cela :
    // MyAppModules.h
    extern const struct LogModules_s {
    _LogModule_t Config;
    _LogModule_t DataModel;
    _LogModule_t UI;
    _LogModule_t WebService;
    ...
    } LogModules;

    // MyAppModules.m
    const struct LogModules_s LogModules = {
    .Config = { "CONFIG", LOG_LEVEL_INFO },
    .DataModel = { "DATAMODEL", LOG_LEVEL_INFO },
    .UI = { "UI", LOG_LEVEL_INFO },
    .WebService = { "WebService", LOG_LEVEL_VERBOSE },
    ...
    };
    Comme ça ils sont tous regroupés dans une seule struct et je les utilise via "LogModules.WebService" par exemple, ce que je trouve plus parlant (Ainsi, le nom de la const struct "LogModules" en préfixe ça fait un peu "namespace")
  • Merci !


     


    est-ce que ce qui suit marcherait :



    //
    // MyClassCoreData
    //

    #define MyLogError(frmt, ...) NFLogError(LogModule.CoreData, frmt, ...)



    de façon à  ne pas se coltiner le LogModule.CoreData dans toute la classe...


  • AliGatorAliGator Membre, Modérateur
    Oui, et c'est d'ailleurs ce que je fais quand j'ai une grosse classe où je sais que tous mes logs dans cette classe devront aller dans le même module.
  • devulderdevulder Membre
    octobre 2013 modifié #49

    Bon c'est pas une macro mais bon a savoir  :)



    static int IsC99()
    {
    return (2//* */2
    == 2);
    }

    #include <stdio.h>

    int main()
    {
    if (IsC99())
    printf("hello from C99 or beyond\n");
    else
    printf("hello from C89 or earlier\n");
    return 0;
    }


    trouvé ici https://gist.github.com/nolanw/899789


  • psychoh13psychoh13 Mothership Developer Membre


    Bon c'est pas une macro mais bon a savoir  :)



    static int IsC99()
    {
    return (2//* */2
    == 2);
    }

    #include <stdio.h>

    int main()
    {
    if (IsC99())
    printf("hello from C99 or beyond\n");
    else
    printf("hello from C89 or earlier\n");
    return 0;
    }


    trouvé ici https://gist.github.com/nolanw/899789




     


    Te rends-tu compte que tu as un technique beaucoup plus simple pour savoir que t'es en C99?



    #if __STDC_VERSION__ >= 199901L
    // Code C99 ou plus
    #else
    // Code C89 ou moins
    #endif

    Le problème avec la technique que tu donnes c'est que le seul intérêt de tester la version du langage c'est savoir si certaines fonctionnalités sont disponibles. Si elles ne le sont pas, bah ça compile pas donc avoir une fonction marche pas vraiment.


    Et dans Clang tu as aussi la possibilité d'utiliser __has_feature, __has_extension ou __has_attribute pour voir si une fonctionnalité est autorisé par le compilateur.

Connectez-vous ou Inscrivez-vous pour répondre.