MarcWan
MarcWan

Reputation: 2973

Is [self class] special in Objective-C

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

Answers (2)

rob mayoff
rob mayoff

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

bbum
bbum

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

Related Questions