The Objective-C object model

Posted by Peter J. Jones on

If you’re an Objective-C developer you can get a lot done without understanding the C roots in Objective-C or the object model employed by Objective-C. In fact, trying to learn the object model can be intimidating and confusing because some peculiar complexities.

Even if it’s a little complex, it’s a worthy endeavor to learn the Objective-C object model because you may end up needing to interact with the Objective-C runtime someday, and understanding the object model will be very useful in that situation.

Grab a cup of tea or coffee and follow along with me while we explore the Objective-C object model.

Objects are instances of a class

Sure, this may sound obvious, but it’s worth taking a few seconds to really consider what it means when we say that an object is an instance of a class. Take the following code for example:

NSString *name = 
  [NSString stringWithFormat:@"%@", @"Peter"];

This is a rather contrived example but it’s important to demonstrate some of the moving parts in the Objective-C runtime. When the code above is executed we end up with a variable called name that is an instance of the NSString class. Please consider the following:

To make this more concrete take a look at the following diagram:

Object Method Dispatch

The blue box represents the name variable (an instance of the NSString class). Using the diagram above let’s look at what happens if you send the length message to the name variable:

NSUInteger len = [name length];
  1. The first thing that Objective-C does is ask the name variable which class it was instantiated from. Since all the methods are held in the class, that’s where it will start looking for the length method.

  2. Since the class of name object is NSString, Objective-C goes to the NSString class and searches for the length method.

  3. If Objective-C finds the length method in the NSString class it will stop searching and execute the method that it found. Otherwise it will continue searching the inheritance hierarchy for the method.

I should note that the process I’m describing has been simplified. I’m not considering other places that methods could be stored (e.g. Objective-C categories).

Classes are really objects too

Given that a class holds methods for its instances, you might be wondering where class methods are stored. Let’s look at the code that created the name variable again:

NSString *name = 
  [NSString stringWithFormat:@"%@", @"Peter"];

In the code above, the stringWithFormat: message was sent to the NSString class. Can classes receive messages, and if so where are those methods kept? In this case, the Objective-C syntax is covering something up, it’s hiding the fact that NSString is also an object.

If NSString is an object, that means that it must have been instantiated from a class that is holding its methods. This is true, but before we dig into it let’s look at some more code:

@interface Person : NSObject {}
+ (void) aClassMethod;
- (void) anInstanceMethod;

You’ve probably seen this many, many times. But what is really going on?

This can be very confusing because the same name is being used over and over again. Going back to our name variable, we can say the following:

Here’s another diagram:

Metaclass Method Dispatch

This time the blue box represents the NSString object. Here’s the creation of the name object again:

NSString *name = 
  [NSString stringWithFormat:@"%@", @"Peter"];

When the stringWithFormat: message is sent to the NSString object Objective-C will:

  1. Ask the NSString object for it’s class, which is the NSString metaclass.

  2. It will then start searching the NSString metaclass for the stringWithFormat: method. If it doesn’t find the method there it will continue up the inheritance hierarchy.

Naturally, since the NSString class inherits from the NSObject class, the NSString metaclass inherits from the NSObject metaclass.

Wacky NSObject inheritance

If you’ve made it this far you can rest assured that you know enough about the Objective-C object model to know a lot more about what’s going on in your code at run time. There’s just one more thing that you may want to know: Why does it look like the NSObject metaclass inherits from the NSObject class? Because it does.

Consider the following:

It’s a bit wacky, but if you look at the diagram above it should start to make sense.

About the Author

Peter J. Jones has been a professional software engineer for over 20 years and is deeply passionate about helping programmers improve the skills of their craft. He is the author of Effective Ruby: 48 Specific Ways to Write Better Ruby. Peter can be reached through our contact page or his twitter account.