"Initializer元素不是编译时常量"为什么?

sub*_*ero 13 xcode objective-c ios

我有这个代码:

- (NSString *) calculate: (uint) position {
    static NSArray * localArray = [NSArray arrayWithArray: self.container.objects ];
    // some un related code
    return obj;
}
Run Code Online (Sandbox Code Playgroud)

编译器抱怨说:"Initializer元素不是编译时常量".它发生在我向localArray添加"static"时.但为什么?

Ada*_*eld 29

因为[NSArray arrayWithArray: self.container.objects ]它不是编译时常量,所以它是必须在运行时计算的表达式.在C和Objective-C中,static函数内部的变量必须用编译时常量初始化,而C++和Objective-C++更宽松并允许非编译时常量.

要么将代码编译为Objective-C++,要么将其重构为以下内容:

static NSArray *localArray = nil;
if (localArray == nil)
    localArray = [NSArray arrayWithArray: self.container.objects ];
Run Code Online (Sandbox Code Playgroud)

这非常类似于编译器将为static使用非编译时常量初始化的变量在引擎盖下生成的代码(实际上,它将使用第二个全局标志来指示值是否已初始化,而不是使用像nil这里的哨兵价值;在这种情况下,我们假设localArray永远不会nil).如果需要,可以查看编译器的反汇编.

  • 我建议使用`dispatch_once()`来初始化`localArray`.它是线程安全且非常有效的. (2认同)

Dir*_*nry 5

您无法使用将在运行时已知/修改的非静态值初始化静态变量.

你应该做这样的事情:

static NSArray *localArray = nil;
localArray = ...;
Run Code Online (Sandbox Code Playgroud)

第一条指令将在您的应用生命周期中执行一次.每次调用calculate:方法时都会执行第二条指令.

尽管如此,请注意使用静态变量可能导致错误行为,如果做得不好,所以如果你对这些行为感到不安,你可能不应该使用它们.

  • +1"第一条指令将在您的应用生命周期中执行一次." (2认同)