Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I use an NSArray as a global constant?

I'm using a set of Constant.m files, one per target, to define specific things for each target. For example:

// Constants.h
extern NSString * const kDatabaseFileName;
//Constants.m
NSString * const kDatabaseFileName = @"target_one.sqlite";

I'd also like to define an NSArray for each of my targets:

NSArray * const kLabelNames = [[NSArray alloc] initWithObjects:
    @"nameLabel", @"addressLabel", nil];

But this gives "error: initializer element is not constant". Using 'arrayWithObjects` doesn't work either. Is this because the strings in my array are not constants?

How can I set up an array as a global constant? Thanks.

like image 748
nevan king Avatar asked Jul 22 '10 19:07

nevan king


People also ask

How do you declare NSArray in Objective C?

Creating NSArray Objects Using Array Literals In addition to the provided initializers, such as initWithObjects: , you can create an NSArray object using an array literal. In Objective-C, the compiler generates code that makes an underlying call to the init(objects:count:) method.

How do you create a constant array?

To create a const array in JavaScript we need to write const before the array name. The individual array elements can be reassigned but not the whole array.

What is difference between NSArray and NSMutableArray?

The primary difference between NSArray and NSMutableArray is that a mutable array can be changed/modified after it has been allocated and initialized, whereas an immutable array, NSArray , cannot.


3 Answers

In Objective-C, objects can only be allocated in heap, so there's no way to create an NSArray in static memory. However, you can create a C array of pointers to NSString constants like so...

NSString * const kLabelNames[] = {
    @"Foo", @"Bar", @"Baz"
};

...and then you can write class methods like this one...

+ (NSArray *)labelNames
{
    static NSArray *names;
    if (names == nil) {
        names = [[NSArray alloc] initWithObjects:kLabelNames count:3];
    }
    return names;
}

Edit

Note that with the introduction of new technologies such as ARC, Grand Central Dispatch and the new literal syntax for arrays, there's now a more straightforward way to accomplish something similar. Note that the example below also provides greater thread safety, though the original example could have incorporated an @synchronized block, or one of several other mechanisms, to achieve similar results.

+ (NSArray *)labelNames
{
    static NSArray *names;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        names = @[@"Foo", @"Bar", @"Baz"];
    });

    return names;
}

However the above example doesn't completely address the original question though. If a global constant array is truly needed, the preceding example could be rewritten along similar lines as the original answer, while still taking advantage of GCD:

NSString * const kLabelNames[] = {
    @"Foo", @"Bar", @"Baz"
};

+ (NSArray *)labelNames
{
    static NSArray *names;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        names = [NSArray arrayWithObjects:kLabelNames count:3];
    });

    return names;
}
like image 42
jlehr Avatar answered Sep 17 '22 15:09

jlehr


Use a macro:

#define SOME_ARRAY (@[@"blah", @"asdf", @"qwerty"])
like image 22
veegee Avatar answered Sep 18 '22 15:09

veegee


Here's a much simpler approach:

Declare NSString with comma separated elements (or whatever delimiter you want)

NSString *const kLabelNames = @"Foo,Bar,Baz";

Then convert to NSArray whenever you need it:

NSArray *namesArray = [kLabelNames componentsSeparatedByString:@","];
like image 142
AmitP Avatar answered Sep 18 '22 15:09

AmitP