The problem is that you don't have actually have a stuff:
method on the class so methodSignatureForSelector:
will return nil
- it looks like you discovered that and so implemented your own version, but that fails on the super
call and so ends up returning the signature of forwardInvocation:
- which is not what you want!
To get around this you either need to direct the methodSignatureForSelector:
to a class which has the selector, or use a protocol - if a class implements a protocol then it will return the signature for any methods in that protocol even if the methods are not actually implemented by that class.
Here is your sample using a protocol:
@protocol DoProtocol
@optional
+ (void) stuff:(int)x;
@end
@interface Do : NSObject<DoProtocol>
@end
@implementation Do
+ (void)forwardInvocation:(NSInvocation *)i
{
const char* argType = [i.methodSignature getArgumentTypeAtIndex:2];
NSLog(@"%s == %s", argType, @encode(id)); // @ == @
NSLog(@"%s == %s", argType, @encode(int)); // @ == i
}
@end
The @optional
avoids any compiler warnings for unimplemented methods. The default implementation of methodSignatureForSelector:
(from NSObject
) will return a valid signature obtained from the protocol, and so forwardInvocation:
will be called.