Static constructor equivalent in Objective-C?
Solution 1
The +initialize
method is called automatically the first time a class is used, before any class methods are used or instances are created. You should never call +initialize
yourself.
I also wanted to pass along a tidbit I learned that can bite you down the road: +initialize
is inherited by subclasses, and is also called for each subclasses that doesn't implement an +initialize
of their own. This can be especially problematic if you naively implement singleton initialization in +initialize
. The solution is to check the type of the class variable like so:
+ (void) initialize {
if (self == [MyParentClass class]) {
// Once-only initializion
}
// Initialization for this class and any subclasses
}
All classes that descend from NSObject have both +class
and -class
methods that return the Class
object. Since there is only one Class object for each class, we do want to test equality with the ==
operator. You can use this to filter what should happen only once ever, versus once for each distinct class in a hierarchy (which may not yet exist) below a given class.
On a tangential topic, it's worth learning about the following related methods, if you haven't already:
-
- isMemberOfClass:(Class)aClass (true only for
aClass
itself) -
- isKindOfClass:(Class)aClass (true for
aClass
and children) - + isSubclassOfClass:(Class)aClass (same as above, but a class method)
Edit: Check out this post by @bbum that explains more about +initialize
: http://www.friday.com/bbum/2009/09/06/iniailize-can-be-executed-multiple-times-load-not-so-much/
Also, Mike Ash wrote a nice detailed Friday Q&A about the +initialize
and +load
methods:
https://www.mikeash.com/pyblog/friday-qa-2009-05-22-objective-c-class-loading-and-initialization.html
Solution 2
There is the +initialize class method that will be called before a class is used.
Solution 3
A bit of an addendum to this topic:
There is another way to create a 'static constructor' in obj-c, using an __attribute
directive:
// prototype
void myStaticInitMethod(void);
__attribute__((constructor))
void myStaticInitMethod()
{
// code here will be called as soon as the binary is loaded into memory
// before any other code has a chance to call +initialize.
// useful for a situation where you have a struct that must be
// initialized before any calls are made to the class,
// as they would be used as parameters to the constructors.
// e.g.
myStructDef.myVariable1 = "some C string";
myStructDef.myFlag1 = TRUE;
// so when the user calls the code [MyClass createClassFromStruct:myStructDef],
// myStructDef is not junk values.
}
Franklin Munoz
Professional software developer in the Seattle Area, with experience on Windows & Mobile software development
Updated on January 06, 2020Comments
-
Franklin Munoz over 4 years
I'm new to Objective C and I haven't been able to find out if there is the equivalent of a static constructor in the language, that is a static method in a class that will automatically be called before the first instance of such class is instantiated. Or do I need to call the Initialization code myself?
Thanks
-
Franklin Munoz about 15 yearsThank you, that's exactly what I was looking for, but I did searches to "static init", "static initializer", etc and didn't find it.
-
Chuck about 15 yearsIn almost every case, where in Java you'd say "static," you say "class" in Objective-C.
-
user102008 almost 13 years"if ([self class] == [MyParentClass class])"
[self class]
is redundant here. you can just sayif (self == [MyParentClass class])
-
Grady Player almost 12 years+load will do the same thing and looks more in sync with the Objective-C paradigm
-
Richard J. Ross III almost 12 years@Grady Nope, I specifically list a situation in the post where +load is NOT equivalent.
-
Grady Player almost 12 years+initialize would be different, but +load should be the same shouldn't it?
-
Richard J. Ross III almost 12 years@GradyPlayer no. Whether +initialize or +load is used, it's possible for some initial data to be corrupted. Period.
-
Grady Player almost 12 yearsperhaps I don't understand the utility of createClassFromStruct: or I don't understand why you can't execute it from +load
-
Richard J. Ross III almost 12 yearsBecause the value of the struct is copied into the stack before the class is initialized, thus you can have invalid values.
-
Grady Player almost 12 yearswhat struct? myStructDef? i don't understand how that would be different than +load{myStructDef...} what error are you guarding against?
-
David Stein over 11 yearsThank you! Your tidbit answered my question of why a particular static initializer was being invoked twice.
-
user102008 about 11 years@RichardJ.RossIII: according to the documentation for
+load
,+load
methods are called before__attribute__(constructor)
functions -
Richard J. Ross III about 11 years@user102008 yes, but what you are missing is that struct values are copied to a register before the first call to
+alloc
. -
Sam about 10 years@RichardJ.RossIII I don't understand what you are achieving since the code in the
+load
method is executed before the code in a function decorated with theconstructor
attribute. Can you please explain? Perhaps in an edit on your answer. -
denis631 about 9 years@Sam did you understand, what is RichardJ.Rosslll talking about ? I'd like to have a real-life example...
-
Sam about 9 years@denis631 no i never figured out what he's talking about.
-
denis631 about 9 years@Sam I guess you would use __attribute__(constructor) in the following situation: you have 2 classes, class A and class B. You want to implement +load method for both of the classes. The problem is, class B +load method wants to call some methods from class A, but it doesn't know if class A will run +load method before B, because (in this example) it is important, that class's A +load method runs first. So the solution is to implement class A +load method, and to use __attribute__(constructor) for the class B. Now we are sure, that class A is loaded, when we want to use it in our constructor B
-
dgatwood almost 8 yearsYou can also use this if you're extending existing an existing class with a category in a manner that requires you to do some sort of class-level initialization up front. You can't add an initialize method in a category, because it would blow away the one in the class, and if multiple people tried to do that in multiple categories, only one of them would load, and probably nondeterministically. This, however, always works.