objective-cobjective-c-runtimensinvocation

Forwarding call to foreign -init method


Situation

For a project of mine, I'm building some kind of extension. This extension must have a class that implements a method whose declaration is - (id)initWithBundle:(NSBundle *)bundle.

Issue

My extension has multiple classes, but the host app is so badly written that it calls - (id)initWithBundle:(NSBundle *)bundle on different classes, randomly.

I'm not willing to reduce the number of classes, so the only solution left would be to somehow forward to caller to the class that actually implement - (id)initWithBundle:(NSBundle *)bundle (A bit like a HTTP 302). I found many resources on forwarding calls, but not such thing as forwarding an -init method...


Solution

  • init is allowed to return an object other than itself. While I highly recommend fixing the calling code (I can't imagine a case where allowing for code that calls anything "randomly" is even a reasonable idea), if you want to return some other object from init, it works like this:

    - (id)initWithBundle:(NSBundle *)bundle {
        // I don't actually implement this, let's return the class that does
        return [[OtherClass alloc] initWithBundle: bundle];
    }
    

    ARC will deal with throwing you away.

    The caller now has the wrong type of course (they expect your type, and they have some other random object), which is very likely to lead to hijinks, very hard to track bugs, and general sorrow. But it's legal ObjC. And if the two classes have enough overlap of their methods, it might even work.

    In normal cases, this pattern is called a Class Cluster. See What exactly is a so called "Class Cluster" in Objective-C? for some examples.