ios static NSDictionary* const letterValues = @{ ..... } 在方法中不编译

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/22534251/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 23:45:53  来源:igfitidea点击:

static NSDictionary* const letterValues = @{ ..... } in a method does not compile

iosobjective-cstaticnsdictionaryconst

提问by Alexander Farber

In a word game for iPhone:

iPhone 的文字游戏中

app screenshot

应用截图

I'm trying to use the following code in my custom view Tile.m:

我正在尝试在我的自定义视图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];
}

Unfortunately this gives me compile error Initializer element is not a compile-time constantand I have to remove the statickeyword to get my app compile in Xcode (here fullscreen):

不幸的是,这给了我编译错误Initializer element is not a compile-time constant,我必须删除static关键字才能在 Xcode 中编译我的应用程序(这里是全屏):

Xcode screenshot

Xcode 截图

I think I initialize the NSDictionarycorrectly - by using the new Objective-C Literalssyntax.

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

But why can't I use statichere?

但是为什么我static这里不能用呢?

I thought it would be appropriate here to make sure that my letterValuesconstant is set only once?

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

回答by Dave Wood

You can only set a static variable during initialization with a constant. @{} creates an object, thus not a constant.

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

Do this instead:

改为这样做:

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


    ...
}

Some other answers here suggest a check for nil instead of dispatch once, but that can cause issues when creating multiple tiles at the same time (via threads). dispatch_once implements the required locking.

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

回答by Austin

You can use static, but the assignment can't be made on the same line. Try this:

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

- (void)awakeFromNib {
    [super awakeFromNib];

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

The reason is that the @{<key> : <value>}syntax is translated by the compiler into an Objective-C method ([[NSPlaceholderDictionary alloc] initWithObjects:forKeys:count:]), which cannot be resolved at compile-time.

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

回答by Adam

NSDictionaryobjects can't be created at compile time. However, if you need a static object, you can create one. You can, for example, use the initializemethod, like this:

NSDictionary不能在编译时创建对象。但是,如果您需要一个静态对象,则可以创建一个。例如,您可以使用该initialize方法,如下所示:

static NSDictionary* letterValues;

+ (void)initialize
{
    if (self == [MyClass class]) {
        letterValues = @{
                         @"A": @1,
                         @"B": @4,
                         @"C": @4,
                         @"X": @8,
                         @"Y": @3,
                         @"Z": @10,
                         };
    }
}

The if statement is there to prevent multiple calls of your code in MyClasssubclasses.

if 语句用于防止在MyClass子类中多次调用您的代码。

回答by mgyky

Another alternative is using the Macro Approach:

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

Macro (The Easiest) Approach (2020)

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

#define kScreenNames @{ \
        @"HOME":                     @"Home Page", \
        @"SEARCH":                   @"Search Page", \
        @"MYLISTS":                  @"My List", \
        @"MYACCOUNT":                @"My Aaccount" \
}

it's short and elegant.

它简短而优雅。

Then, you can use it like any other NSDictionary.

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

I hope this will help someone on the planet.

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

Best Regards

此致