Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

static initializers in objective C

How do I make static initializers in objective-c (if I have the term correct). Basically I want to do something like this:

static NSString* gTexts[] = 
{
    @"A string.",
    @"Another string.",
}

But I want to do this more struct-like, i.e. have not just an NSString for each element in this array, but instead an NSString plus one NSArray that contains a variable number of MyObjectType where MyObjectType would contain an NSString, a couple ints, etc.

like image 792
Joey Avatar asked Feb 16 '11 05:02

Joey


3 Answers

Since NSArrays and MyObjectTypes are heap-allocated objects, you cannot create them in a static context. You can declare the variables, and then initialize them in a method.

So you cannot do:

static NSArray *myStaticArray = [[NSArray alloc] init....];

Instead, you must do:

static NSArray *myStaticArray = nil;

- (void) someMethod {
  if (myStaticArray == nil) {
    myStaticArray = [[NSArray alloc] init...];
  }
}

This happens to work with constant strings (@"foo", etc), because they are not heap-allocated. They are hardcoded into the binary.

like image 59
Dave DeLong Avatar answered Oct 14 '22 06:10

Dave DeLong


It is very important that you make sure that your static initialization is thread-safe (available in iOS 4.1+)!!!

static NSArray *myStaticArray = nil;

- (void) someMethod {
  static dispatch_once_t onceToken;
  dispatch_once(&onceToken, ^{
    myStaticArray = [[NSArray alloc] init...]
  });
}
like image 21
chrish Avatar answered Oct 14 '22 07:10

chrish


here's one way, if you can live with an objc++ translation:

#import <Foundation/Foundation.h>

namespace { // ok, this storage should preferably be in a function/deferred
    static struct sa { NSString* const s; NSArray* const a; } r = {
      [[NSString alloc] initWithString:@"hello"],
      [[NSArray alloc] initWithObjects:@"w", @"o", @"r", @"l", @"d", @"= =", nil]
    };
}

int main(int argc, const char* argv[]) {
  NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
  NSLog(@"\n\n%@...\n\n...\n%@", r.s, r.a);
  [pool drain];
  return 0;
}
like image 35
justin Avatar answered Oct 14 '22 06:10

justin