Quand utiliser une chaîne statique contre #define

Je suis un peu confus quand il est préférable d’utiliser:

static NSSsortingng *AppQuitGracefullyKey = @"AppQuitGracefully"; 

au lieu de

 #define AppQuitGracefullyKey @"AppQuitGracefully" 

J’ai vu des questions comme celles-ci pour C ou C ++, et je pense que ce qui est différent ici, c’est spécifiquement pour Objective C, en utilisant un object et sur un périphérique comme l’iPhone. Je ne saisis pas encore

Une utilisation serait:

 appQuitGracefully = [[NSUserDefaults standardUserDefaults] integerForKey: AppQuitGracefullyKey]; 

Ou c’est juste une question de style?

Merci.

Si vous utilisez un fichier statique, le compilateur incorporera exactement une copie de la chaîne dans votre fichier binary et transmettra simplement des pointeurs à cette chaîne, ce qui générera des fichiers binarys plus compacts. Si vous utilisez un #define, une copie distincte de la chaîne sera stockée dans la source à chaque utilisation. La coalescence constante des chaînes gérera un grand nombre de dups, mais vous faites en sorte que le lieur fonctionne plus fort sans aucune raison.

Voir “statique const” vs “#define” vs “enum” . Le principal avantage de la static est la sécurité de type.

En dehors de cela, l’approche #define introduit une flexibilité de la concaténation de chaînes en ligne qui ne peut pas être réalisée avec des variables statiques, par exemple

 #define ROOT_PATH @"/System/Library/Frameworks" [[NSBundle bundleWithPath:ROOT_PATH@"/UIKit.framework"] load]; 

mais ce n’est probablement pas un bon style :).

Après quelques recherches ( cette question / réponse entre autres), je pense qu’il est important de dire que chaque fois que vous utilisez un littéral de chaîne @"AppQuitGracefully" une chaîne constante est créée, et peu importe le nombre de fois que vous l’utilisez, le même object

Donc je pense (et je m’excuse si je me trompe) que cette phrase dans la réponse ci-dessus est fausse: If you use a #define, there will be a separate copy of the ssortingng stored in the source on each use.

Je ne recommanderais en fait ni l’un ni l’autre, vous devriez plutôt utiliser extern . Objective-c définit déjà FOUNDATION_EXPORT qui est plus portable que extern , donc une instance NSSsortingng globale ressemblerait à ceci:

.h

 FOUNDATION_EXPORT NSSsortingng * const AppQuitGracefullyKey; 

.m

 NSSsortingng * const AppQuitGracefullyKey = @"AppQuitGracefully"; 

Je mets généralement ces fichiers de déclaration (tels que MyProjectDecl.h ) et les importe quand j’en ai besoin.

Il existe quelques différences avec ces approches:

  • #define a plusieurs inconvénients, tels que ne pas être de type sécurisé. Il est vrai qu’il existe des solutions pour cela (comme #define ((int)1) ) mais à quoi ça sert? De plus, cette approche présente des inconvénients pour le débogage. Les compilateurs préfèrent les constantes. Voir cette discussion.
  • les globaux statiques sont visibles dans le fichier qu’ils sont déclarés.
  • extern rend la variable visible à tous les fichiers. Cela contraste avec statique.

Statique et externe diffèrent en visibilité. Il convient également de noter qu’aucune de ces approches ne duplique la chaîne (même pas #define ) car le compilateur utilise Ssortingng Interning pour empêcher cela. Dans ce post de NSHipster, ils montrent des preuves:

 NSSsortingng *a = @"Hello"; NSSsortingng *b = @"Hello"; BOOL wtf = (a == b); // YES 

L’opérateur == renvoie YES uniquement si les deux variables pointent vers la même instance. Et comme vous pouvez le voir, c’est le cas.

La conclusion est la suivante: utilisez FOUNDATION_EXPORT pour les constantes globales. Il est compatible avec le débogage et sera visible partout dans votre projet.

J’utilise static quand j’ai besoin d’exporter des symboles NSSsortingng d’une bibliothèque ou d’un framework. J’utilise #define quand j’ai besoin d’une chaîne dans de nombreux endroits que je peux changer facilement. De toute façon, le compilateur et l’éditeur de liens s’occuperont des optimisations.

UTILISATION #define:

vous ne pouvez pas déboguer la valeur de l’identifiant

travailler avec #define et les autres macros sont un travail de pré-processeur, quand vous appuyez sur Build / Run en premier il va prétraiter le code source, il va fonctionner avec toutes les macros (en commençant par le symbole #),

Supposons que vous ayez créé,

 #define LanguageTypeEnglish @"en" 

et utilisé à 2 endroits dans votre code.

 NSSsortingng *language = LanguageTypeEnglish; NSSsortingng *languageCode = LanguageTypeEnglish; 

il remplacera “LanguageTypeEnglish” par @"en" , à tous les endroits. Donc, 2 copies de @"en" seront générées. c’est à dire

 NSSsortingng *language = @"en"; NSSsortingng *languageCode = @"en"; 

Rappelez-vous, jusqu’à ce que ce processus, le compilateur n’est pas dans l’image.

Après le prétraitement de toutes les macros, le complier apparaît, et il obtiendra un code de saisie comme celui-ci,

 NSSsortingng *language = @"en"; NSSsortingng *languageCode = @"en"; 

et comstackr

UTILISATION statique:

il respecte la scope et est de type sécurisé. vous pouvez déboguer la valeur de l’identifiant

Pendant le processus de compilation si le compilateur a été trouvé,

 static NSSsortingng *LanguageTypeRussian = @"ru"; 

alors il vérifiera si la variable avec le même nom est stockée précédemment, si oui, elle ne fera que passer le pointeur de cette variable, sinon elle créera cette variable et passera son pointeur, la prochaine fois elle ne fera que passer le pointeur de le même.

Donc, en utilisant statique, une seule copie de la variable est générée dans la scope.