views:

724

answers:

2

When implementing an +initialize or +load method in one of your Objective-C classes, should you always start with this kind of guard?:

@implementation MyClass

+ (void)initialize {
    if (self == [MyClass class]) {
        ...
    }
}

...
@end

Seems like code in +load and +initialize usually only wants to be executed once. So this would help avoid dupe execution when subclasses load/initialize.

I guess I'm just wanting some reinforcement from some ObjC wizards that this is necessary/common practice...

What's the common wisdom on this? would you recommend always doing this?

Is your advice the same for both +load and +initialize, or is there a difference in they way they should be handled?

thanks.

+1  A: 

Yes, you should do this in your intialize and load methods if you are initializing globals that should only be initialized once.

That said, there are a number of cases where you may avoid it...

You shouldn't wrap with this conditional if the work needs to be performed on every inheritant of every class:

  • For example, adding all inherited class names for each class to a set.
  • edited addition: or you're establishing KVO dependencies (as mentioned by eJames)

There are also situations where you just needn't bother:

  • If the actions you perform are idempotent (don't change values if repeated)
  • The class is "sealed" (has no descendants by design)

The "idempotent" part is relevant. An initializer should just be setting the initial state (which should be the same each time). In a good initializer, repetition shouldn't matter. Although I suppose that if you forget to wrap the method in the conditional when it does matter, this might be annoying.

edited addition: A different approach, that properly reflects any initialize-only-once requirements would be to test if your properties to initialize are initialized already. i.e.

id myGlobalObject = nil;

+(void)initialize
{
    if (myGlobalObject == nil)
    {
        myGlobalObject = [[MyGlobalClass alloc] init];
    }
}
Matt Gallagher
+5  A: 
e.James
hmmm.. sounds like this is even more nuanced than i realized...
Todd Ditchendorf
If you're targeting Leopard you shouldn't be using +setKeys: triggerChangeNotificationsForDependentKey: but should instead be implementing +(NSSet *)keyPathsForValuesAffecting<key>, and that takes care of the second point.
Ashley Clark