Classes and Meta-Classes and Methods in Objective-C

Classes and Meta-Classes and Methods in Objective-C

A small post on how instance and class methods are implemented in objective-c, and how to add methods at runtime.

Classes and Meta-Classes

Recently I commented about classes and meta-classes in Objective-C. All objects have a type (their class). All objects have a reference to that class as a Class object (see definitions below). Instance methods for a given type are effectively stored in that Class object. Class-level methods, however, are not. Class-level methods are stored on the Class object’s reference to its meta-class object (also of type Class).

This is very important when you want to add or swizzle instance-level and class-level methods at runtime, because you must add instance-level methods to the type’s class, and class-level methods by adding them to the meta-class for that class. Below is a simple interface/implementation demonstrating fetching classes and meta-classes (partially taken from Classes and Meta-classes but with additions).

It outputs something like the following:

DKObject's class is 0x100002908
DKObject's class is 0x100002908
DKObject's class is 0x100002908
DKObject's meta-class is 0x100002930
DKObject's meta-class is 0x100002930
DKObject's meta-class is 0x100002930

(Just note that the references are different for the class and meta-class.)

The one tricky point is that the class method for Class objects does not return the meta-class for that class (as you might think it would), but returns itself. Since the meta-class contains the class-level methods, in order to add a class-level method, we have to get the meta-class for a class. As shown above, you can od:

(Note that a Class is also an id.)

The above may not be an exhaustive list of ways of doing this.

Apple’s developer docs on runtime manipulation functions

Adding Methods

There are probably many posts explaining this (though I didn’t find many), but you use the class_addMethod() function to add both instance-level and class-level methods. The function itself does not differentiate which kind of method you are adding – it can’t from the selector. You pass a type’s Class reference for adding instance-level methods, and a meta-class Class reference for adding class-level methods.

So, let’s say we want to add the following two methods to NSObject:

The code to do that would be:

Note that for class-level methods, we pass the meta-class Class, fetched with object_getClass(). The last two parameters of the method are well documented elsewhere, so I won’t bother to explain them here.