web-dev-qa-db-ja.com

Objective-C静的、外部、パブリック変数

ヘッダーファイルをインポートすることでどこからでもアクセスできる変数が必要ですが、作成されるのはそのうちの1つだけであるという意味で静的である必要もあります。 .mファイルで、指定します

static BOOL LogStuff = NO;

そして、初期化メソッドでロギング値を設定します:

+ (void)initialize
{
    LogStuff = ... //whatever
}

しかし、.hファイルをインポートすることでどこからでも変数にアクセスできるようにしたいので、次のようなことをしたいと思います。

static extern BOOL LogStuff;

しかし、私はそれを行うことはできません。私がやろうとしていることをすることは可能ですか?ありがとう

38
JPC

Objective-Cのstaticは、静的クラスデータメンバおよび静的クラスメソッドのコンテキストにおいて、C++クラスのstaticとは異なることを意味します。 CおよびObjective-Cでは、グローバルスコープのstatic変数または関数は、そのシンボルに内部リンケージがあることを意味します。

内部リンケージとは、そのシンボルが現在のソースファイルである現在のtranslation unitに対してローカルであることを意味します(.cまたは.m)コンパイルされ、再帰的にインクルードされるすべてのヘッダーファイル。そのシンボルは別の翻訳単位から参照することはできません。また、同じ名前を持つ他の翻訳単位で内部リンケージを持つ他のシンボルを持つことができます。

そのため、変数をstaticとして宣言するヘッダーファイルがある場合、そのヘッダーを含む各ソースファイルは、separateグローバル変数を取得します。 1つのソースファイルは同じ変数を参照しますが、異なるソースファイルの参照はdifferent変数を参照します。

単一のグローバル変数が必要な場合、C++のようにクラススコープに含めることはできません。 1つのオプションは、externalリンケージを使用してグローバル変数を作成することです:ヘッダーファイルでexternキーワードを使用して変数を宣言し、次にoneソースファイル、externキーワードなしでグローバルスコープで定義します。内部リンケージと外部リンケージは相互に排他的です。externstaticの両方として変数を宣言することはできません。

Panos推奨 の代替案は、変数の代わりにクラスメソッドを使用することです。これにより、機能がクラスのスコープ内に保持されます。これは意味的に意味があります。また、@private希望する場合。パフォーマンスにわずかなペナルティを追加しますが、それがアプリケーションのボトルネックになることはほとんどありません(疑わしい場合は、常に最初にプロファイルを作成してください)。

124
Adam Rosenfield

LogStuffが静的クラスフィールドである場合、静的getterおよびsetterを実装できますか?

+ (void)setLogStuff:(BOOL)aLogStuff;
+ (BOOL)logStuff;
4
Panos

宣言するextern BOOLヘッダーファイル。 #importヘッダーは、外部シンボルが静的であるかどうかを知りません。

3
NSResponder

個別のグローバル変数(ソースファイルごとに1つ):

// .h
static NSString * aStatic;

//.m
static NSString * aStatic = @"separate";

一意のグローバル変数:

// .h
extern NSString * anExtern;

// .m
NSString * anExtern = @"global";
1
SwiftArchitect

私は通常、このレイアウトを静的に使用します。

NSMutableArray *macroArray;
BOOL keepMacro;

+ (void) startMacro
{
    if (macroArray == nil)
    {
        macroArray = [[NSMutableArray alloc] initWithCapacity:100];
    }

    [macroArray removeAllObjects];
    keepMacro = YES;
}

これは私のアプリケーションのstartMacroコマンドです。 BoolmacroArrayは両方とも静的ですが、staticまたはexternとして宣言されていないことに注意してください。

これはベストプラクティスではないかもしれませんが、これは私がしていることです。

0
The Lazy Coder