Objective-C // Runtime Method Injection

While building our Actionscript Native Extensions we've had to learn a lot about Objective C for the iOS versions. One trick that we'd like to share is how to inject a method into an instance of a class at runtime. This is necessary for several of the extensions we've done and it took me a while to figure out how to do this so I thought I'd share.

Quick Links:

Overall, we are going to create a method and add this method into an instance of a class as a member method. This is critically important when a delegate for an application has already been defined but we don't have access to the source or compilation options of this class. So if we want to implement or add functionality to this delegate we must inject it at runtime.

The functionality we are going to use is included as part of the objective c runtime library which we get access to by including the objc/runtime header at the top of your file.

  1. #include <objc/runtime.h>

The method must be defined in a very particular format to be provided to the class_addMethod function:

  1. BOOL class_addMethod(Class cls, SEL name, IMP imp, const char *types)

This method is simply a C function with at least two arguments, self and _cmd. Any arguments after these two must match the arguments of the method you are trying to implement. Say you need to implement the following method:

  1. - (void)someMethodWithArguments: (int)anArgument;

Then you'll need a C function like:

  1. void someMethodWithArgumentsIMP( id self, SEL _cmd, int anArgument )
  2. {
  3. // implementation ....
  4. }

The implementation of the class can use self to reference the instance of the class the method is injected into.

Continuing in with the above injection example, lets say we have a class instance named instanceOfAClass that we need to implement the someMethodWithArguments as defined above, then we'll call:

  1. class_addMethod(
  2. [instanceOfAClass class],
  3. @selector(someMethodWithArguments),
  4. (IMP)someMethodWithArgumentsIMP,
  5. "v@:i"
  6. );

The last argument in this function call is of particular importance. It describes the types of the arguments supplied to the method. The first character is the return type, in our example this is void which is represented by "v". The following characters are all of the arguments of our c function.

The second and third characters must be "@:" since the function must take at least two arguments — self and _cmd. Following these are all of the methods arguments, ie int anArgument which is represented by an "i". For a listing of all the type encodings see the reference here.

Once you've successfully called this function you'll see the code in the c function, someMethodWithArgumentsIMP being executed whenever the class calls the method someMethodWithArguments. It's a very simple, but powerful method of being able to add functionality to a class at runtime.

Published by

Michael

http://michaelarchbold.com

Leave a Reply

Your email address will not be published. Required fields are marked *