Fun and games (with rewritten rules) in Objective-C

An object-oriented programming environment is not a set of rules. Programs do not need to be constructed according to the rules supplied by the environment. An object-oriented environment includes tools for constructing new rules, and programs can use these to good effect. Let’s build multiple method inheritance for Objective-C, to see a new set of rules.

The goal

Given three classes, A, B, and C:

@interface A : NSObject



@implementation A

-(NSInteger)a { return [self double:6]; }


@interface B : NSObject



@implementation B

-(NSInteger)b { return 30; }


@interface C : NSObject



@implementation C

  return a*2;

-c { return @([self a] + [self b]); }


We want to find the value of a C instance’s c property. That depends on its values of a and b, but that class doesn’t have those methods. We should add them.

int main(int argc, const char * argv[]) {
  @autoreleasepool {
    C *c = [C new];
    [c addSuperclass:[A class]];
    [c addSuperclass:[B class]];
    NSLog(@"The answer is %@", c.c);

We want the following output:

2015-02-17 20:23:36.810 Mixins[59019:418112] The answer is 42

Find a method from any superclass

Clearly there’s some chicanery going on here. I’ve changed the rules: methods are no longer simply being looked up in a single class. My instance of C has three superclasses: A, B and NSObject.

@interface NSObject (Mixable)

- (void)addSuperclass:(Class)aSuperclass;


@implementation NSObject (Mixable)

  return objc_getAssociatedObject(self, "superclasses");

- (void)addSuperclass:(Class)aSuperclass
  id superclasses = [self superclasses]?:@[];
  id newSupers = [superclasses arrayByAddingObject:aSuperclass];
  objc_setAssociatedObject(self, "superclasses", newSupers, OBJC_ASSOCIATION_RETAIN_NONATOMIC);

- (Class)superclassForSelector:(SEL)aSelector
  __block Class potentialSuperclass = Nil;
  [[self superclasses] enumerateObjectsUsingBlock:^(Class aClass, NSUInteger idx, BOOL *stop) {
    if ([aClass instancesRespondToSelector:aSelector])
      potentialSuperclass = aClass;
      *stop = YES;
  return potentialSuperclass;

- (NSMethodSignature *)original_methodSignatureForSelector:(SEL)aSelector
  NSMethodSignature *signature = [self original_methodSignatureForSelector:aSelector];
  if (signature)
    return signature;
  Class potentialSuperclass = [self superclassForSelector:aSelector];
  return [potentialSuperclass instanceMethodSignatureForSelector:aSelector];

- (void)forwardInvocation:(NSInvocation *)anInvocation
  SEL aSelector = [anInvocation selector];
  Class potentialSuperclass = [self superclassForSelector:aSelector];
  [anInvocation invokeSuperImplementation:potentialSuperclass];

+ (void)load
  if (self == [NSObject class])
    method_exchangeImplementations(class_getInstanceMethod(self, @selector(original_methodSignatureForSelector:)),
                                   class_getInstanceMethod(self, @selector(methodSignatureForSelector:)));


Now invoke that method.

When you write [super foo], the Objective-C runtime needs to send a message to your object but tell the resolution machinery to look at the superclass for the method implementation, not at the current class. It uses a function objc_msgSendSuper to do this. In this case, I don’t have the superclass: I have a superclass, one of potentially many. So what I need to do is more general than what messaging super does.

Luckily for me, objc_msgSendSuper is already sufficiently general. It receives a pointer to self, just like the usual objc_msgSend, but in addition it receives a pointer to the class to be used as the superclass. By controlling that class pointer, I can tell the system which superclass to use.

A category on NSInvocation calls objc_msgSendSuper with the appropriate arguments to get the correct method from the correct class. But how can it call the function correctly? Objective-C messages could receive any number of arguments of any type, and return a value of any type. Constructing a function call when the parameters are discovered at runtime is the job of libffi, which is used here (not shown: a simple, if boring, map of Objective-C value encodings to libffi type descriptions).

@interface NSInvocation (SuperInvoke)



@implementation NSInvocation (SuperInvoke)

- (BOOL)isVoidReturn
  return (strcmp([[self methodSignature] methodReturnType], "v") == 0);

  NSMethodSignature *signature = [self methodSignature];
  if (superclass)
    struct objc_super super_class = { .receiver = [self target],
      .super_class = superclass };
    struct objc_super *superPointer = &super_class;
    ffi_cif callInterface;
    NSUInteger argsCount = [signature numberOfArguments];
    ffi_type **args = malloc(sizeof(ffi_type *) * argsCount);
    for (int i = 0; i < argsCount; i++) {
      args[i] = [self ffiTypeForObjCType:[signature getArgumentTypeAtIndex:i]];
    ffi_type *returnType;
    if ([self isVoidReturn]) {
      returnType = &ffi_type_void;
    else {
      returnType = [self ffiTypeForObjCType:[signature methodReturnType]];
    ffi_status status = ffi_prep_cif(&callInterface,
                                     (unsigned int)[signature numberOfArguments],
    if (status != FFI_OK) {
      NSLog(@"I can't make an FFI frame");

    void *argsBuffer = malloc([signature frameLength]);
    int cursor = 0;
    cursor += args[0]->size;
    void **values = malloc([signature numberOfArguments] * sizeof(void  *));
    values[0] = &superPointer;

    for (int i = 1; i < [signature numberOfArguments]; i++) {
      values[i] = (argsBuffer + cursor);
      [self getArgument:values[i] atIndex:i];
      cursor += args[i]->size;
    if ([self isVoidReturn]) {
      ffi_call(&callInterface, objc_msgSendSuper, NULL, values);
    } else {
      void *result = malloc(returnType->size);
      ffi_call(&callInterface, objc_msgSendSuper, result, values);
      [self setReturnValue:result];



You’ve seen this conclusion before: blah blah awesome power of the runtime. It doesn’t just let you do expressive things in the Objective-C game, it lets you define a better game.

Leave a Reply

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

To create code blocks or other preformatted text, indent by four spaces:

    This will be displayed in a monospaced font. The first four 
    spaces will be stripped off, but all other whitespace
    will be preserved.
    Markdown is turned off in code blocks:
     [This is not a link](

To create not a block, but an inline code span, use backticks:

Here is some inline `code`.

For more help see

This site uses Akismet to reduce spam. Learn how your comment data is processed.