As I understand it, an unimplemented method gets resolved in the following way:
- resolveInstanceMethod: / resolveClassMethod: gets a chance to implement the method
- forwardingTargetForSelector: gets a chance to forward to a delegate
- forwardInvocation: gets a chance to handle the method as it sees fit.
Where is this three-step process defined? I'd like to handle it myself as NSInvocation might be too heavyweight for my needs. I've had a poke around the runtime source and can't really see anything.
It looks like the old runtime would call forward:args: on the receiver, to do this but that seems to have gone from the new one. I'm guessing that the process must be defined by the framework rather than the runtime, since it'd be strange if the runtime depended on Cocoa to the extent of requiring NSInvocation to handle messages. Is it maybe an undocumented method that gets called on NSObject / NSProxy?
Edit:
It looks like the runtime declares, but never defines, a C function which is called when objc_msgSend can't find an implementation:
id objc_msgForward(id object,SEL message,...);
I don't work for Apple, so I don't know how Foundation implements this, but at least in the case of Cocotron, they use:
id objc_msgForward(id object,SEL message,...)
{
Class class=object->isa;
struct objc_method *method;
void *arguments=&object;
if((method=class_getInstanceMethod(class,@selector(forwardSelector:arguments:)))!=NULL)
return method->method_imp(object,@selector(forwardSelector:arguments:),message,arguments);
else
{
OBJCRaiseException("OBJCDoesNotRecognizeSelector","%c[%s %s(%d)]", class_isMetaClass(class) ? '+' : '-', class->name,sel_getName(message),message);
return nil;
}
}
adding a forwardSelector:arguments:
method doesn't seem to work, so I'm guessing this is specific to Cocotron. Anyone know what objc_msgForward
does in Foundation?