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.
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.
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.
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.
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;
}
Use a macro:
#define SOME_ARRAY (@[@"blah", @"asdf", @"qwerty"])
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:@","];
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With