Dynamic Method Injection (in Objective-C)
When asked what I like the most from the Objective-C programming language, I often refer to its dynamic underpinnings.
Although Objective-C is a superset of C, the way its designers decided to implement the Object model was dynamic. This provides a strong contrast with C++, which, although a superset of C as well, is a static-typed language.
In this post I will show how you can use the Objective-C runtime to dynamically add a method to an (Objective-C) class at runtime.
Let’s start by creating a Dummy class that has no methods whatsoever. I will put everything in the same file for the sake of simplicity, but in real-life code, you’d want to have separate files for the interface and the implementation.
#import <Foundation/Foundation.h> @interface Dummy : NSObject @end @implementation Dummy @end
Now, let’s implement a method to be dynamically added to Dummy. Interestingly enough, methods to add need to be implemented as C functions.
Here’s our implementation:
void newMethod(id self, SEL _cmd) { printf("Hello from a dynamically added method! (self=%p)\n", self); }
Now, let’s go to the main function and see how we can inject “newMethod” into the Dummy class. We will need to import the Objective-C runtime.
#import <objc/runtime.h> int main(int argc, char* argv[]) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; // Add method to Dummy class (args explained below) class_addMethod([Dummy class], @selector(printHello), (IMP)newMethod, "v@:"); Dummy* instance = [[Dummy alloc] init]; [instance printHello]; [instance release]; [pool release]; return 0; }
When running this program, an output similar to this will be produced:
Hello from a dynamically added method! (self=0x10ad143a0)
So, let’s see how the method was added.
The heavylifting here is done by the class_addMethod function. This function, coming from the Objective-C runtime, allows you to register a new method in a class.
This feat requires a pointer to the function that implements the method (“newMethod”), but lets you assign any name you want to it (I chose “printHello”). Notice that’s the message I send to the Dummy instance.
The strangest parameter is perhaps the last “v@:”. This is actually a code for the argument types received by the “newMethod” function. All valid type codes can be found in the Apple reference, but to make things easier, “v@:” means that the function returns void (v) and receives an Object and a selector.
Adding methods dynamically is pretty good feature, but it seems little complicated in Objective-C.
In Smalltalk:
myMethodString := ‘newMethod: aString
^MessageBox notify: aString’.
Dummy compile: myMethodString.
Anyway you have the possibility to do it.
Regards,
Bruno
Muy interesante, me gustan este tipo de artículos! ¿Hay posibilidad de compilar Objective-C para plataformas no OS X/iOs?
@Martin: check out: http://www.alejandrosegovia.net/2011/11/04/brief-introduction-to-objective-c/ :)