Je suis un peu confus quant au meilleur moment pour l'utiliser:
static NSString *AppQuitGracefullyKey = @"AppQuitGracefully";
au lieu de
#define AppQuitGracefullyKey @"AppQuitGracefully"
J'ai vu des questions comme celle-ci pour C ou C++, et je pense que ce qui est différent ici, c'est que c'est spécifiquement pour Objective C, en utilisant un objet, et sur un appareil comme l'iPhone, il peut y avoir des problèmes de pile, d'espace de code ou de mémoire qui 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 statique, le compilateur incorporera exactement une copie de la chaîne dans votre binaire et passera simplement des pointeurs vers cette chaîne, ce qui donnera des binaires plus compacts. Si vous utilisez un #define, il y aura une copie séparée de la chaîne stockée dans la source à chaque utilisation. La coalescence constante des chaînes gérera de nombreux doublons, mais vous faites travailler l'éditeur de liens plus dur sans raison.
Voir "const statique" vs "#define" vs "enum" . Le principal avantage de static
est la sécurité des types.
À part cela, le #define
l'approche introduit une flexibilité de concaténation de chaînes en ligne qui ne peut pas être effectué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 :).
En fait, je ne recommanderais ni l'un ni l'autre, vous devriez utiliser extern
à la place. Objective-c définit déjà FOUNDATION_EXPORT
Qui est plus portable que extern
, donc une instance globale de NSString
ressemblerait à ceci:
.h
FOUNDATION_EXPORT NSString * const AppQuitGracefullyKey;
.m
NSString * const AppQuitGracefullyKey = @"AppQuitGracefully";
Je les mets généralement dans des fichiers de déclaration (tels que MyProjectDecl.h
) Et les importe quand j'en ai besoin.
Il existe quelques différences entre ces approches:
#define ((int)1)
) mais quel est le point? De plus, cette approche présente des inconvénients de débogage. Les compilateurs préfèrent les constantes. Voir cette discussion.La visibilité statique et externe diffèrent. Il est également à noter qu'aucune de ces approches ne duplique la chaîne (pas même #define
) Car le compilateur utilise String Interning pour empêcher cela. Dans ce post NSHipster ils montrent la preuve:
NSString *a = @"Hello";
NSString *b = @"Hello";
BOOL wtf = (a == b); // YES
L'opérateur ==
Ne renvoie YES
que si les deux variables pointent vers la même instance. Et comme vous pouvez le voir, c'est le cas.
La conclusion est: utilisez FOUNDATION_EXPORT
Pour les constantes globales. Il est convivial pour le débogage et sera visible dans tout votre projet.
Après avoir fait quelques recherches ( this question/réponse, entre autres), je pense qu'il est important de dire qu'à tout moment lorsque vous utilisez un littéral de chaîne @"AppQuitGracefully"
une chaîne constante est créée, et peu importe combien de fois vous l'utilisez, elle pointera vers le même objet .
Je pense donc (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 string stored in the source on each use.
TILISATION #define:
vous ne pouvez pas déboguer la valeur de l'identifiant
travailler avec #define et d'autres macros est un travail de pré-processeur, lorsque vous appuyez d'abord sur Build/Run, il pré-traitera le code source, il fonctionnera avec toutes les macros (en commençant par le symbole #),
Supposons que vous ayez créé,
#define LanguageTypeEnglish @"en"
et utilisé cela à 2 endroits dans votre code.
NSString *language = LanguageTypeEnglish;
NSString *languageCode = LanguageTypeEnglish;
il remplacera "LanguageTypeEnglish" par @"en"
, partout. Donc 2 copies de @"en"
sera généré. c'est à dire
NSString *language = @"en";
NSString *languageCode = @"en";
Rappelez-vous, jusqu'à ce processus, le compilateur n'est pas dans l'image.
Après le prétraitement de toutes les macros, complier apparaît dans l'image, et il obtiendra le code d'entrée comme ceci,
NSString *language = @"en";
NSString *languageCode = @"en";
et compilez-le.
TILISATION statique:
il respecte la portée et est de type sûr. vous pouvez déboguer la valeur de l'identifiant
Pendant le processus de compilation si le compilateur est trouvé,
static NSString *LanguageTypeRussian = @"ru";
alors il vérifiera si la variable avec le même nom stocké précédemment, si oui, il ne passera que le pointeur de cette variable, sinon, il créera cette variable et passera son pointeur, la prochaine fois il passera seulement le pointeur de le même.
Ainsi, en utilisant statique, une seule copie de variable est générée dans la portée.
J'utilise static
lorsque j'ai besoin d'exporter des symboles NSString à partir d'une bibliothèque ou d'un framework. J'utilise #define
quand j'ai besoin d'une chaîne à plusieurs endroits que je peux changer facilement. Quoi qu'il en soit, le compilateur et l'éditeur de liens se chargeront des optimisations.