Reputation: 2973
I ran across some code today that does the following:
- (instancetype)initWithBlah:(Blah)blah {
NSLog(@"Initialising instance of %@", [self class]);
if ((self = [super init]) != nil) {
// blargh
}
return self;
}
Now, this seems weird because self is used in [self class]
before it's actually set a few lines later, but never seems to crash here and the compiler doesn't squawk, and it actually works.
Is [self class]
treated specially by the objc compiler and just statically evaluates to the Class object?
Upvotes: 1
Views: 531
Reputation: 385590
[self class]
is not treated specially by the compiler. It is a normal message send.
Constructing an object in Objective-C on Apple platforms looks like this:
UIView *view = [[UIView alloc] init];
There are two steps: alloc
and init
.
First, you allocate the object's heap storage by sending the alloc
message to the class object. Almost all class objects simply inherit the alloc
method of NSObject
. This method allocates the heap storage using malloc
(or something like it), fills the storage with zeros, and sets the isa
Instance variable of the object to point at itself (the class object that received the alloc
method).
Second, you ask the newly created object to initialize itself by sending it an init
message. Unlike alloc
, init
is very often overridden, or classes provide a class-specific initialization message (like your initWithBlah:
).
By the time an object receives an init
-type message, its isa
instance variable has already been set to point at its class object and all its other instances variables have been set to zero.
When a normal object receives a class
message, it simply returns the class referenced by its isa
.
I'm simplifying here, because the modern Objective-C runtime supports something called “non-pointer isa”, where other things are encoded in the isa
field in addition to the class pointer, so the class
method has to do a little more work to get the class pointer from the field. But the isa
field is still initialized by alloc
.
There's also something called tagged pointers where the object's class is embedded in directly in the object reference. For these objects, class
works differently, but only a small number of system classes uses tagged pointers, so tagged pointers never affect the way class
works for your own user-defined classes.
Upvotes: 6
Reputation: 162712
Nope. Nothing special about.
self
is actually set on entry to the body of the method. But [super init
might return a different instance, hence the re-assignment. So, technically, that log statement could log something that is no longer true by the end of the initializer.
You'll probably want to read this:
Why [object doSomething] and not [*object doSomething]?
Upvotes: 4