このトピックで NSStrings に使用されているのと同じスタイルを使用して、いくつかの NSNumber 定数を作成したいと考えています。つまり、個別の constants.h/.m ファイルを作成し、それらにアクセスする必要があるクラスにそれらをインポートしています。
4 に答える
これを行う際の問題は、コンパイル時定数NSNumberのようなものがないことです。NSStringだけがその区別を取得します。NSNumbersは常に動的に作成されます。プログラムの起動時に実行される関数を使用して変数を初期化することにより、これを偽造することができます。あなたのオプション:
+load
初期化を実行するメソッドを使用してクラスを作成します。定数を含むファイルに、。を含む関数を含めます
__attribute__((constructor))
。したがって、たとえば:// Constants.m NSNumber *someGlobalNumber; __attribute__((constructor)) static void InitGlobalNumber() { someGlobalNumber = [[NSNumber numberWithInteger:1] retain]; }
ただし、もちろん、起動プロセスの早い段階で実行される他の関数でこれらの数値を確実に使用することはできません。これは通常問題ではありませんが、覚えておく価値があります。
私が数回見た他のオプションは、変数への生のアクセスを与える代わりに、数値のアクセサーを持つクラスを持つことです。少し重めのデザインですが、ブードゥーっぽさも少なく、魅力もあります。
残念ながら、現在、NSNumber
定数を生成できるのと同じ方法で定数を生成することはできませんNSString
。実行しようとすると、コンパイルエラーが発生します
NSNumber * const kNumberConstant = @2; // This doesn't work.
ただし、代わりにプリミティブを使用できます。
NSInteger const kSomeIntValue = 10;
基本的に、次の 3 つの部分で目的に近いものを実現できます。
.h ファイル:
extern NSNumber *MyFirstConstant;
.m ファイル
NSNumber *MyFirstConstant;
AppDelegate.m
+(void)initialize
{
MyFirstConstant = @5;
...
}
AppDelegate は他のどのコードよりも前に実行されることが保証されており、initialize は AppDelegate で呼び出される最初のメソッドであるため、基本的に、アプリを実行する前にすべての定数が設定されていることを保証できます。
アップデート:
数年後、整数の NSNumber 定数を作成できることに気づきました...しかし、それはハックです:
#define CONST_INT_NSNUMBER( x ) ((__bridge NSNumber * const)(void * const)(( x << 8 ) | 0x27))
NSNumber * const number = CONST_INT_NSNUMBER(123) ;
これが機能するのは、特定の整数 NSNumber がタグ付きポインターとして格納されているためです。
元の答え:
あなたはそれをすることはできません。
NSNumber * const mynumber = @5.5;
与えます:
初期化要素はコンパイル時の定数ではありません
コンパイラには、コンパイル時の定数NSString
オブジェクトを作成するための特別な機能があることを意味しますが、他のタイプのオブジェクトはありません。
ただし、これを行うことができます:
.h :
extern NSNumber * kConstantNumber ;
.m :
NSNumber * kConstantNumber ;
@implementation NSNumber (InitializeConstants)
+(void)load
{
kConstantNumber = @42;
// ... and the rest ...
}
@end