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.
The quick answer is: No.
An in-depth discussion of this matter can be found on the Apple developer mailing list.
The gist of it is that:
+initialize
on super classes before it is called on subclasses.
+initialize
method will not trigger dependent KVO notifications.
For an example of point #2, be sure to read this post in the thread mentioned above.
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:
There are also situations where you just needn't bother:
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];
}
}
YES!!!!
Because the initialize method of a class may be invoked many times. e.g. when you implement initialize in parent class, and don't implement in sub class, then you call sub class first, the initialize of parent will invoked twice.
@implementation BaseClass
+ (void)initialize
{
NSLog(@"BaseClass initialize self=%@, class=%@", self, [BaseClass class]);
}
@end
@interface SubClass : BaseClass
@end
@implementation SubClass
// don't implement the initialize method
@end
==================
now when you call SubClass first, just like
[SNSBaseSubLogic alloc]
look the debug console, output:
BaseClass initialize self=BaseClass, class=BaseClass
BaseClass initialize self=SubClass, class=BaseClass
so, you must use
+ (void)initialize
{
if (self == [BaseClass class]) {
NSLog(@"BaseClass initialize self=%@, class=%@", self, [BaseClass class]);
}
}
to ensure the method body execute once.
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