Je veux avoir une variable à laquelle je peux accéder n'importe où en important un fichier d'en-tête mais je veux aussi qu'elle soit statique dans le sens où il n'y en a qu'une créée. Dans mon fichier .m, je précise
static BOOL LogStuff = NO;
et dans la méthode d'initialisation j'ai défini la valeur de journalisation:
+ (void)initialize
{
LogStuff = ... //whatever
}
Cependant, je veux pouvoir accéder à ma variable n'importe où en important le fichier .h, donc je veux faire quelque chose comme ceci:
static extern BOOL LogStuff;
mais je ne suis pas autorisé à le faire. Est-il possible de faire ce que j'essaie de faire? Merci
static
dans Objective-C signifie une chose différente de static
dans une classe C++, dans le contexte des membres de données de classe statique et des méthodes de classe statique. En C et Objective-C, une variable ou une fonction static
de portée globale signifie que ce symbole a lien interne.
La liaison interne signifie que ce symbole est local à l'unité de traduction, qui est le fichier source actuel (.c
Ou .m
) En cours de compilation et tous les fichiers d'en-tête qu'il inclut récursivement. Ce symbole ne peut pas être référencé à partir d'une unité de traduction différente et vous pouvez avoir d'autres symboles avec une liaison interne dans d'autres unités de traduction du même nom.
Donc, si vous avez un fichier d'en-tête déclarant une variable comme static
, chaque fichier source qui inclut cet en-tête obtient une variable globale séparée - toutes les références à cette variable dans un fichier source fera référence à la même variable, mais les références dans différents fichiers sources feront référence aux variables différentes.
Si vous voulez avoir une seule variable globale, vous ne pouvez pas l'avoir dans la portée de classe comme en C++. Une option consiste à créer une variable globale avec liaison externe: déclarer la variable avec le mot clé extern
dans un fichier d'en-tête, puis dans un fichier source, définissez-le à portée globale sans le mot clé extern
. La liaison interne et la liaison externe s'excluent mutuellement - vous ne pouvez pas avoir une variable déclarée à la fois extern
et static
.
Une alternative, comme Panos a suggéré , serait d'utiliser une méthode de classe au lieu d'une variable. Cela maintient la fonctionnalité dans le cadre de la classe, ce qui est plus logique sur le plan sémantique, et vous pouvez également le faire @private
Si vous le souhaitez. Cela ajoute une pénalité de performance marginale, mais il est très peu probable que ce soit le goulot d'étranglement dans votre application (si vous pensez que c'est le cas, toujours le profil en premier).
Si LogStuff
est un champ de classe statique, vous pouvez peut-être implémenter un getter et un setter statiques?
+ (void)setLogStuff:(BOOL)aLogStuff;
+ (BOOL)logStuff;
Déclarez-le extern BOOL
dans votre fichier d'en-tête. Fichiers qui #import
votre en-tête ne sait pas ou ne se soucie pas si le symbole externe est statique ou non.
Variable globale distincte (une par fichier source):
// .h
static NSString * aStatic;
//.m
static NSString * aStatic = @"separate";
Variable globale unique:
// .h
extern NSString * anExtern;
// .m
NSString * anExtern = @"global";
J'utilise normalement cette disposition pour ma statique:
NSMutableArray *macroArray;
BOOL keepMacro;
+ (void) startMacro
{
if (macroArray == nil)
{
macroArray = [[NSMutableArray alloc] initWithCapacity:100];
}
[macroArray removeAllObjects];
keepMacro = YES;
}
Il s'agit de la commande startMacro
dans mon application. Bool
et macroArray
sont statiques, mais notez qu'ils ne sont pas déclarés static
ou extern
.
Ce n'est peut-être pas la meilleure pratique, mais c'est ce que je fais.