カスタムビューで次のコードを使用しようとしています Tile.m :
- (void)awakeFromNib
{
[super awakeFromNib];
static NSDictionary* const letterValues = @{
@"A": @1,
@"B": @4,
@"C": @4,
// ...
@"X": @8,
@"Y": @3,
@"Z": @10,
};
NSString* randomLetter = [kLetters substringWithRange:[kLetters rangeOfComposedCharacterSequenceAtIndex:arc4random_uniform(kLetters.length)]];
int letterValue = [letterValues[randomLetter] integerValue];
_smallLetter.text = _bigLetter.text = randomLetter;
_smallValue.text = _bigValue.text = [NSString stringWithFormat:@"%d", letterValue];
}
残念ながら、これによりコンパイルエラーが発生します初期化要素はコンパイル時の定数ではありません。アプリを取得するにはstatic
キーワードを削除する必要がありますXcodeでコンパイル(ここでは fullscreen ):
新しい Objective-C Literals 構文を使用して、NSDictionary
を正しく初期化すると思います。
しかし、ここでstatic
を使用できないのはなぜですか?
私のletterValues
定数が1度だけ設定されることを確認することは、ここでは適切だと思いましたか?
静的変数は、初期化中に定数でのみ設定できます。 @ {}はオブジェクトを作成するため、定数ではありません。
代わりにこれを行ってください:
- (void)awakeFromNib
{
[super awakeFromNib];
static NSDictionary* letterValues = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
letterValues = @{
@"A": @1,
@"B": @4,
@"C": @4,
// ...
@"X": @8,
@"Y": @3,
@"Z": @10,
};
});
...
}
ここでの他のいくつかの回答は、一度ディスパッチするのではなくnilのチェックを提案していますが、これは複数のタイルを同時に(スレッドを介して)作成するときに問題を引き起こす可能性があります。 dispatch_onceは必要なロックを実装します。
静的を使用できますが、同じ行で割り当てを行うことはできません。これを試して:
- (void)awakeFromNib {
[super awakeFromNib];
static NSDictionary* letterValues = nil;
if (!letterValues) {
letterValues = @{@"A": @1,
@"B": @4,
@"C": @4,
// ...
@"X": @8,
@"Y": @3,
@"Z": @10};
}
...
}
その理由は、@{<key> : <value>}
構文は、コンパイラーによってObjective-Cメソッド([[NSPlaceholderDictionary alloc] initWithObjects:forKeys:count:]
)、コンパイル時に解決できません。
NSDictionary
オブジェクトはコンパイル時に作成できません。ただし、静的オブジェクトが必要な場合は作成できます。たとえば、次のようにinitialize
メソッドを使用できます。
static NSDictionary* letterValues;
+ (void)initialize
{
if (self == [MyClass class]) {
letterValues = @{
@"A": @1,
@"B": @4,
@"C": @4,
@"X": @8,
@"Y": @3,
@"Z": @10,
};
}
}
Ifステートメントは、MyClass
サブクラスでのコードの複数呼び出しを防ぐためにあります。