The root class of most Objective-C class hierarchies, from which subclasses inherit a basic interface to the runtime system and the ability to behave as Objective-C objects.
Creating a Custom ClassGo ahead an choose “Objective-C class” and hit Next. For the class name, enter “Person.” Make it a subclass of NSObject. NSObject is the base class for all objects in Apple's developer environment. It provides basic properties and functions for memory management and allocation.
The Objective-C runtime is a runtime library that provides support for the dynamic properties of the Objective-C language, and as such is linked to by all Objective-C apps. Objective-C runtime library support functions are implemented in the shared library found at /usr/lib/libobjc.
load
messageThe runtime sends the load
message to each class object, very soon after the class object is loaded in the process's address space. For classes that are part of the program's executable file, the runtime sends the load
message very early in the process's lifetime. For classes that are in a shared (dynamically-loaded) library, the runtime sends the load message just after the shared library is loaded into the process's address space.
Furthermore, the runtime only sends load
to a class object if that class object itself implements the load
method. Example:
@interface Superclass : NSObject
@end
@interface Subclass : Superclass
@end
@implementation Superclass
+ (void)load {
NSLog(@"in Superclass load");
}
@end
@implementation Subclass
// ... load not implemented in this class
@end
The runtime sends the load
message to the Superclass
class object. It does not send the load
message to the Subclass
class object, even though Subclass
inherits the method from Superclass
.
The runtime sends the load
message to a class object after it has sent the load
message to all of the class's superclass objects (if those superclass objects implement load
) and all of the class objects in shared libraries you link to. But you don't know which other classes in your own executable have received load
yet.
Every class that your process loads into its address space will receive a load
message, if it implements the load
method, regardless of whether your process makes any other use of the class.
You can see how the runtime looks up the load
method as a special case in the _class_getLoadMethod
of objc-runtime-new.mm
, and calls it directly from call_class_loads
in objc-loadmethod.mm
.
The runtime also runs the load
method of every category it loads, even if several categories on the same class implement load
. This is unusual. Normally, if two categories define the same method on the same class, one of the methods will “win” and be used, and the other method will never be called.
initialize
MethodThe runtime calls the initialize
method on a class object just before sending the first message (other than load
or initialize
) to the class object or any instances of the class. This message is sent using the normal mechanism, so if your class doesn't implement initialize
, but inherits from a class that does, then your class will use its superclass's initialize
. The runtime will send the initialize
to all of a class's superclasses first (if the superclasses haven't already been sent initialize
).
Example:
@interface Superclass : NSObject
@end
@interface Subclass : Superclass
@end
@implementation Superclass
+ (void)initialize {
NSLog(@"in Superclass initialize; self = %@", self);
}
@end
@implementation Subclass
// ... initialize not implemented in this class
@end
int main(int argc, char *argv[]) {
@autoreleasepool {
Subclass *object = [[Subclass alloc] init];
}
return 0;
}
This program prints two lines of output:
2012-11-10 16:18:38.984 testApp[7498:c07] in Superclass initialize; self = Superclass
2012-11-10 16:18:38.987 testApp[7498:c07] in Superclass initialize; self = Subclass
Since the system sends the initialize
method lazily, a class won't receive the message unless your program actually sends messages to the class (or a subclass, or instances of the class or subclasses). And by the time you receive initialize
, every class in your process should have already received load
(if appropriate).
The canonical way to implement initialize
is this:
@implementation Someclass
+ (void)initialize {
if (self == [Someclass class]) {
// do whatever
}
}
The point of this pattern is to avoid Someclass
re-initializing itself when it has a subclass that doesn't implement initialize
.
The runtime sends the initialize
message in the _class_initialize
function in objc-initialize.mm
. You can see that it uses objc_msgSend
to send it, which is the normal message-sending function.
Check out Mike Ash's Friday Q&A on this topic.
What it means is don't override +initialize
in a category, you'll probably break something.
+load
is called once per class or category that implements +load
, as soon as that class or category is loaded. When it says "statically linked" it means compiled into your app binary. The +load
methods on classes thus compiled will be executed when your app launches, probably before it enters main()
. When it says "dynamically loaded", it means loaded via plugin bundles or a call to dlopen()
. If you're on iOS, you can ignore that case.
+initialize
is called the first time a message is sent to the class, just before it handles that message. This (obviously) only happens once. If you override +initialize
in a category, one of three things will happen:
This is why you should never override +initialize
in a category - in fact it's quite dangerous to try and replace any method in a category because you're never sure what you're replacing or whether your own replacement will itself be switched out by another category.
BTW, another issue to consider with +initialize
is that if someone subclasses you, you'll potentially get called once for your class and once for each subclass. If you're doing something like setting up static
variables, you'll want to guard against that: either with dispatch_once()
or by testing self == [MyClass class]
.
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