このコードをコンパイルすると、「初期化子要素はコンパイル時定数ではありません」というエラーが表示されます。誰でもその理由を説明できますか?
#import "PreferencesController.h"
@implementation PreferencesController
- (id)init
{
self = [super init];
if (self) {
// Initialization code here.
}
return self;
}
NSImage* imageSegment = [[NSImage alloc] initWithContentsOfFile:@"/User/asd.jpg"];//error here
関数のスコープ外で変数を定義すると、その変数の値は実際に実行可能ファイルに書き込まれます。これは、定数値のみを使用できることを意味します。コンパイル時のランタイム環境に関するすべて(使用可能なクラス、その構造など)がわからないため、特定の文字列が指定されている場合を除き、ランタイムまでにObjective Cオブジェクトを作成することはできません。構造とその方法にとどまることが保証されています。行うべきことは、変数をnilに初期化し、+initialize
を使用してイメージを作成することです。 initialize
は、クラスで他のメソッドが呼び出される前に呼び出されるクラスメソッドです。
例:
NSImage *imageSegment = nil;
+ (void)initialize {
if(!imageSegment)
imageSegment = [[NSImage alloc] initWithContentsOfFile:@"/User/asd.jpg"];
}
- (id)init {
self = [super init];
if (self) {
// Initialization code here.
}
return self;
}
グローバル変数は、4
または0.0
または@"constant string"
またはnil
などの定数値に初期化する必要があります。 init
などのオブジェクトコンストラクターは、定数値を返しません。
グローバル変数が必要な場合は、nil
に初期化してからクラスメソッドを使用して返す必要があります。
NSImage *segment = nil;
+ (NSImage *)imageSegment
{
if (segment == nil) segment = [[NSImage alloc] initWithContentsOfFile:@"/user/asd.jpg"];
return segment;
}
本質的に動的なコードで静的変数を初期化するようコンパイラーに要求しているからです。
理由は、ソースコード(静的変数)の関数の外側でimageSegment
を定義しているためです。
そのような場合、関数の呼び出しやクラスの割り当てなど、コードの実行を初期化に含めることはできません。初期化子は、コンパイル時に値がわかっている定数でなければなりません。
その後、init
メソッド内で静的変数を初期化できます(その宣言をinitに延期する場合)。
以下に示すように、マクロを確実に#defineできます。コンパイラは、コンパイルの前に「IMAGE_SEGMENT」をその値に置き換えます。配列のグローバルルックアップを定義することはできますが、グローバル変数とは異なります。マクロを展開すると、インラインコードのように機能するため、毎回新しいイメージが作成されます。したがって、マクロの使用場所に注意すれば、グローバル変数の作成を効果的に達成できたでしょう。
#define IMAGE_SEGMENT [[NSImage alloc] initWithContentsOfFile:@"/User/asd.jpg"];
次に、以下に示すように、必要な場所で使用します。以下のコードが実行されるたびに、新しいオブジェクトが新しいメモリポインターで作成されます。
imageSegment = IMAGE_SEGMENT