静态NSDictionary*const letterValues = @ {.....}在一个方法中无法编译

Ale*_*ber 13 static const objective-c nsdictionary ios

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];
}
Run Code Online (Sandbox Code Playgroud)

不幸的是,这给了我编译错误Initializer元素不是编译时常量,我必须删除static关键字以使我的应用程序在Xcode中编译(这里全屏):

Xcode截图

我认为我NSDictionary正确地初始化- 使用新的Objective-C Literals语法.

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

我认为在这里确保我的letterValues常量只设置一次是合适的吗?

Dav*_*ood 41

您只能在初始化期间使用常量设置静态变量.@ {}创建一个对象,因此不是常量.

改为:

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


    ...
}
Run Code Online (Sandbox Code Playgroud)

这里的一些其他答案建议检查nil而不是一次调度,但这可能会在同时创建多个tile时(通过线程)导致问题.dispatch_once实现所需的锁定.


Aus*_*tin 5

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

- (void)awakeFromNib {
    [super awakeFromNib];

    static NSDictionary* letterValues = nil;
    if (!letterValues) {
        letterValues = @{@"A": @1,
                         @"B": @4,
                         @"C": @4,
                         // ...
                         @"X": @8,
                         @"Y": @3,
                         @"Z": @10};
    }
    ...
}
Run Code Online (Sandbox Code Playgroud)

原因是@{<key> : <value>}编译器将语法转换为Objective-C方法([[NSPlaceholderDictionary alloc] initWithObjects:forKeys:count:]),这在编译时无法解析.


mgy*_*yky 5

另一种选择是使用宏观方法:

宏观(最简单)方法(2021)

#define kScreenNames @{ \
        @"HOME":                     @"Home Page", \
        @"SEARCH":                   @"Search Page", \
        @"MYLISTS":                  @"My List", \
        @"MYACCOUNT":                @"My Aaccount" \
}
Run Code Online (Sandbox Code Playgroud)

它简短而优雅。

然后,您可以像任何其他 NSDictionary 一样使用它。

我希望这能帮助地球上的某个人。

最好的