1

I have a NSString that should be constant in my class. I used the following code to accomplish this:

@interface DefinitionViewController ()
@end

static NSString *preamble;

@implementation DefinitionViewController {

}

+(void)initialize {
  if (self == [DefinitionViewController class]) {
    NSString *path = [[NSBundle mainBundle] pathForResource:@"preamble" ofType:@"html"];
    preamble = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding
    error:nil];
  }
}

It seems to work fine. I worry about using a file read inside an initialize. Is there a more appropriate means to accomplish the same goal (shared static string)? I could bury this inside my code, but it was much easier to maintain the somewhat large string as an external file.

Thanks for any advice.

Bill
  • 1,588
  • 12
  • 21

1 Answers1

2

"I worry about using a file read inside an initialize".

Don't (worry). The fact that it is, for example, a class method is utterly irrelevant. It is code. It runs and does its job. It is sound code, it runs coherently at a coherent time, and your app bundle is a real thing that really contains the resource. There's no problem here.

If you want to postpone creation of the string, and make assurance doubly sure that the string is not initialized twice, you could instead use a singleton pattern so that the string value is not generated until the first time it is explicitly requested:

+ (NSString*) preamble {
    static NSString* preamble = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        NSString *path = [[NSBundle mainBundle] pathForResource:@"preamble" ofType:@"html"];
        preamble = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];
    });
    return preamble;
}

But there is no special need for this. (EDIT: But see, to the contrary, the comment below of @bbum, who Really Knows Stuff.)

matt
  • 515,959
  • 87
  • 875
  • 1,141
  • If I understood the documentation correctly, there is no race condition with `initialize`, so a singleton is really overkill, correct? And I also assume that a file read from the app bundle is not going to cause a deadlock. Thanks. – Bill Feb 10 '14 at 05:35
  • @Bill The `+initialize` method should not be used for "heavy lifting". It can cause any number of issues ranging from unexpected class initialization order dependencies to slow launch times that are hard to fix to difficulties refactoring later. In this case, it *probably* isn't going to hurt, but your suggesting to use the singleton pattern is definitely a better option (with the caveat that it is still a form of lazy initialization that can be problematic during optimizations phases). – bbum Feb 10 '14 at 05:52