编译错误:"初始化元素不是编译时常量"

Nic*_*ick 73 cocoa compiler-errors initialization global-variables objective-c

编译此代码时,我得到错误"初始化元素不是编译时常量".有谁能解释为什么?

#import "PreferencesController.h"

@implementation PreferencesController

- (id)init
{
    self = [super init];
    if (self) {
        // Initialization code here.
    }

    return self;
}


NSImage* imageSegment = [[NSImage alloc] initWithContentsOfFile:@"/User/asd.jpg"];//error here
Run Code Online (Sandbox Code Playgroud)

ugh*_*fhw 102

当您在函数范围之外定义变量时,该变量的值实际上会写入您的可执行文件中.这意味着您只能使用常量值.由于您在编译时不了解运行时环境的所有内容(哪些类可用,它们的结构是什么等),因此除了常量字符串之外,您无法创建目标c对象,而这些字符串是特定的结构并保证保持这种状态.您应该做的是将变量初始化为nil并用于+initialize创建图像.initialize是一个类方法,它将在您的类上调用任何其他方法之前调用.

例:

NSImage *imageSegment = nil;
+ (void)initialize {
    if(!imageSegment)
        imageSegment = [[NSImage alloc] initWithContentsOfFile:@"/User/asd.jpg"];
}
- (id)init {
    self = [super init];
    if (self) {
        // Initialization code here.
    }

    return self;
}
Run Code Online (Sandbox Code Playgroud)

  • 另一种选择是将源文件的类型从Objective-C切换到Objective-C++(或将其从.m重命名为.mm,具有相同的效果).在C++中,这样的初始化程序不需要是编译时常量值,原始代码可以正常工作. (10认同)
  • 另一种选择是使用带有`__attribute __((构造函数))`的函数. (4认同)
  • 有没有办法以这种方式声明“const”?即只能设置一次且不能再次设置的变量? (3认同)

mip*_*adi 22

全局变量必须被初始化为一恒定值,如40.0@"constant string"nil.对象构造函数(例如)init不返回常量值.

如果要拥有全局变量,则应将其初始化为nil,然后使用类方法返回它:

NSImage *segment = nil;

+ (NSImage *)imageSegment
{
    if (segment == nil) segment = [[NSImage alloc] initWithContentsOfFile:@"/user/asd.jpg"];
    return segment;
}
Run Code Online (Sandbox Code Playgroud)

  • @bluesm:Objective-C编译器使用一些技巧来创建一个被视为常量值的字符串. (4认同)

bbu*_*bum 11

因为您要求编译器使用本质上动态的代码初始化静态变量.


ser*_*gio 5

原因是您imageSegment在源代码(静态变量)中定义了函数的外部.

在这种情况下,初始化不能包括代码的执行,如调用函数或分配类.初始化程序必须是一个常量,其值在编译时是已知的.

然后,您可以在init方法内部初始化静态变量(如果将其声明推迟到init).