Compiler error: "initializer element is not a compile-time constant"

Objective CCocoaInitializationCompiler ErrorsGlobal Variables

Objective C Problem Overview


When compiling this code, I get the error "initializer element is not a compile-time constant". Can anyone explain why?

#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

Objective C Solutions


Solution 1 - Objective C

When you define a variable outside the scope of a function, that variable's value is actually written into your executable file. This means you can only use a constant value. Since you don't know everything about the runtime environment at compile time (which classes are available, what is their structure, etc.), you cannot create objective c objects until runtime, with the exception of constant strings, which are given a specific structure and guaranteed to stay that way. What you should do is initialize the variable to nil and use +initialize to create your image. initialize is a class method which will be called before any other method is called on your class.

Example:

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;
}

Solution 2 - Objective C

A global variable has to be initialized to a constant value, like 4 or 0.0 or @"constant string" or nil. A object constructor, such as init, does not return a constant value.

If you want to have a global variable, you should initialize it to nil and then return it using a class method:

NSImage *segment = nil;

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

Solution 3 - Objective C

Because you are asking the compiler to initialize a static variable with code that is inherently dynamic.

Solution 4 - Objective C

The reason is that your are defining your imageSegment outside of a function in your source code (static variable).

In such cases, the initialization cannot include execution of code, like calling a function or allocation a class. Initializer must be a constant whose value is known at compile time.

You can then initialize your static variable inside of your init method (if you postpone its declaration to init).

Solution 5 - Objective C

You can certainly #define a macro as shown below. The compiler will replace "IMAGE_SEGMENT" with its value before compilation. While you will achieve defining a global lookup for your array, it is not the same as a global variable. When the macro is expanded, it works just like inline code and so a new image is created each time. So if you are careful in where you use the macro, then you would have effectively achieved creating a global variable.

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

Then use it where you need it as shown below. Each time the below code is executed, a new object is created with a new memory pointer.

imageSegment = IMAGE_SEGMENT

Solution 6 - Objective C

You can use the static singleton approach with dispatch_once:

#define STATIC_VAR(type, code) ^type() { \
	static type object; \
	static dispatch_once_t onceToken; \
	dispatch_once(&onceToken, ^{ \
		object = code; \
	}); \
	return object; \
};

#define let __auto_type const

let imageSegment = STATIC_VAR(UIImage*, [[UIImage alloc] initWithContentsOfFile:@"image.jpg"]);
let imageRect = STATIC_VAR(CGRect, CGRectMake(0, 0, 100, 100));

// How to use:

- (void)viewDidLoad {
	[super viewDidLoad];
	
	self.imageView.image = imageSegment();
	self.imageView.frame = imageRect();
}

It is thread safe, works lazily with any type and makes only a single instance.

Solution 7 - Objective C

I got this error while practicing C language, my code that I was trying to run was this

#include <stdio.h>
#include <stdlib.h>

typedef struct
{
	char *name;
	int age;
} person;

person *p = (person *)malloc(sizeof(person));

and I realized while reading answers, that in C, I should have main function, which I forgot to use, so put the person code in main function, thus removing the error as follows

#include <stdio.h>
#include <stdlib.h>

typedef struct
{
	char *name;
	int age;
} person;

int main()
{

	person *p = (person *)malloc(sizeof(person));
	return 0;
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionNickView Question on Stackoverflow
Solution 1 - Objective CughoavgfhwView Answer on Stackoverflow
Solution 2 - Objective CmipadiView Answer on Stackoverflow
Solution 3 - Objective CbbumView Answer on Stackoverflow
Solution 4 - Objective CsergioView Answer on Stackoverflow
Solution 5 - Objective CKris SubramanianView Answer on Stackoverflow
Solution 6 - Objective CiUriiView Answer on Stackoverflow
Solution 7 - Objective CAkshay Vijay JainView Answer on Stackoverflow