How do I declare an array as a constant in Objective-c?

The following code is giving me errors:

//  constants.h
extern NSArray const *testArray;
//  constants.m
NSArray const *testArray = [NSArray arrayWithObjects:  @"foo", @"bar", nil];

The error I get is
initializer element is not constant

Or if I take away the pointer indicator (*) I get:
statically allocated instance of Objective-C class 'NSArray'


In short, you can't. Objective-C objects are, with the exception of NSString, only ever created at runtime. Thus, you can't use an expression to initialize them.

There are a handful of approaches.

(1) Declare NSArray *testArray without the const keyword and then have a bit of code that sets up the value that is invoked very early during application lifecycle.

(2) Declare a convenient class method that returns the array, then use a static NSArray *myArray within that method and treat it as a singleton (search SO for "objective-c singleton" for about a zillion answers on how to instantiate).


A little late to the party, but since you're not changing the values through the course of the program, if you were only dealing with strings, you could do the following by declaring your array using a C array:

extern NSString * const MY_CONSTANT_STRING_ARRAY[];

in your constants.h file, and then in your constants.m you could add objects to it like so:

NSString * const MY_CONSTANT_STRING_ARRAY[] = { @"foo", @"bar" };

Then to access a member, you could do a for loop like so with a C sizeof() operator:

This obviously is a C array and not a NSArray so you don't get all of the fun methods attached to it like objectAtIndex:, so you could create a helper function somewhere in your program that loops through all of the strings using the method I outlined above and returns an NSArray (or NSMutableArray even). But, if you were doing what I am and just need a constant array of NSString values to use throughout your program, this method works the best.

Doing it this way encapsulates all of your string array contants in constants.h, and is still available throughout your program by adding constants.h in your .pch file instead of creating a singleton just for this array of values or setting the array with a little code, which sorta defeats the purpose of a constants file because it removes the actual constants out of the constants file..

EDIT per @JesseGumpo's Comment:

Since there may be issues with using sizeof() to determine the size of the array, a simple workaround is to declare the size of the array in your constants file like so:

//.h
extern int SIZE_OF_MY_CONSTANTS_ARRAY;  

///.m
int SIZE_OF_MY_CONSTANTS_ARRAY = 2;

And then to access the members in a for loop you can do so like this:

for (int i=0; i < SIZE_OF_MY_CONSTANTS_ARRAY; i++) 
        NSLog(@"my constant string is: %@", MY_CONSTANT_STRING_ARRAY[i]);

Yes, this doesn't dynamically capture the size of the array, but if you're declaring an array in a constants file you already know the size of that array from the start, so even though it adds two more lines of code, it still accomplishes the task of having an array in a constants file.

If anyone has any more suggestions or may know some other C tricks please leave a comment below!


Here's a macro to do it in one line for a static instance in a method scope.

#define STATIC_ARRAY(x, ...)   \
        static NSArray* x=nil; \
        static dispatch_once_t x##onceToken; \
        dispatch_once(&x##onceToken, ^{ x = @[ __VA_ARGS__ ]; });

Use example

    STATIC_ARRAY(foo, @"thing1", @"thing2", [NSObject new]);

It's pretty easy :

#define arrayTitle [NSArray arrayWithObjects: @"hi",@"foo",nil]

put before implementation and without semicolon.

hope it helps.