静态NSDictionary * const的letterValues = @ {…}在一个方法不会编译

在iPhone的文字游戏中 :

应用截图

我想在我的自定义视图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(这里全屏 )编译:

Xcode截图

我想我正确地初始化NSDictionary – 通过使用新的Objective-C文字语法。

但为什么我不能在这里使用static

我认为这是适当的,以确保我的letterValues常量只设置一次?

你只能在初始化时用一个常量来设置一个静态variables。 @ {}创build一个对象,因此不是一个常量。

做这个,而不是:

 - (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, }; }); ... } 

这里的其他一些答案build议检查一次,而不是一次调度,但这可能会导致在同一时间(通过线程)创build多个磁贴时出现问题。 dispatch_once实现所需的locking。

您可以使用静态,但不能在同一行上进行分配。 尝试这个:

 - (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:] ),在编译时无法parsing。

NSDictionary对象不能在编译时创build。 但是,如果你需要一个静态对象,你可以创build一个。 例如,您可以使用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子类中多次调用您的代码。