Ошибка компилятора: «элемент инициализатора не является константой времени компиляции» - PullRequest
71 голосов
/ 26 мая 2011

При компиляции этого кода я получаю ошибку "элемент инициализатора не является константой времени компиляции"Кто-нибудь может объяснить, почему?

#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

Ответы [ 5 ]

101 голосов
/ 26 мая 2011

Когда вы определяете переменную вне области функции, значение этой переменной фактически записывается в ваш исполняемый файл.Это означает, что вы можете использовать только постоянное значение.Так как вы не знаете все о среде выполнения во время компиляции (какие классы доступны, какова их структура и т. Д.), Вы не можете создавать объекты цели 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;
}
19 голосов
/ 26 мая 2011

Глобальная переменная должна быть инициализирована постоянным значением, например 4 или 0.0 или @"constant string" или nil.Конструктор объекта, такой как init, не возвращает постоянного значения.

Если вы хотите иметь глобальную переменную, вы должны инициализировать ее как nil, а затем вернуть ее с помощью метода класса:

NSImage *segment = nil;

+ (NSImage *)imageSegment
{
    if (segment == nil) segment = [[NSImage alloc] initWithContentsOfFile:@"/user/asd.jpg"];
    return segment;
}
10 голосов
/ 26 мая 2011

Поскольку вы просите компилятор инициализировать статическую переменную с помощью кода, который по своей природе является динамическим.

5 голосов
/ 26 мая 2011

Причина в том, что вы определяете imageSegment вне функции в исходном коде (статическая переменная).

В таких случаях инициализация не может включать выполнение кода, например, вызов функции иливыделение класса.Инициализатор должен быть константой, значение которой известно во время компиляции.

Затем вы можете инициализировать статическую переменную внутри вашего метода init (если вы отложите ее объявление до init).

3 голосов
/ 02 июня 2015

Вы, безусловно, можете # определить макрос, как показано ниже. Компилятор заменит «IMAGE_SEGMENT» его значением перед компиляцией. Хотя вы достигнете определения глобального поиска для вашего массива, это не то же самое, что глобальная переменная. Когда макрос раскрывается, он работает как встроенный код, и каждый раз создается новое изображение. Поэтому, если вы будете осторожны в том, где вы используете макрос, вы бы эффективно добились создания глобальной переменной.

#define IMAGE_SEGMENT [[NSImage alloc] initWithContentsOfFile:@"/User/asd.jpg"];

Затем используйте его там, где вам нужно, как показано ниже. Каждый раз, когда выполняется приведенный ниже код, создается новый объект с новым указателем памяти.

imageSegment = IMAGE_SEGMENT
...