Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I just "swallow" the "unrecognized selector error" by message-forwarding?

I'm just studying the "message-forwarding" of Objective-C. I write a test program to verify if I can "swallow" an unrecognized selector at run-time. So I did this:

- (void) forwardInvocation: (NSInvocation *) anInvocation {
    if ([anInvocation selector] == @selector(testMessage)){
       NSLog(@"Unknow message");
    }
    return;
}

But it still throws "unrecognized selector" error at run time. After searching the resolution I know that I need to override method "methodSignatureForSelector:", so I write another proxy class called "Proxy" and the following method:

(NSMethodSignature *)methodSignatureForSelector:(SEL)selector {
    if ([Proxy instancesRespondToSelector: selector]) {
        return [Proxy instanceMethodSignatureForSelector: selector];
    }   
    return [super methodSignatureForSelector:selector];
}

But, actually, I don't want to implement such another proxy class to accomplish this method. All I want to do is that ignore this unknown selector. But If I just type this, it does not work:

(NSMethodSignature *)methodSignatureForSelector:(SEL)selector {   
    return [super methodSignatureForSelector:selector];
}

So, I wonder there is any way that can simply "swallow" this error? (Not using exception handler, I wanna a "forwarding"-like way). Thanks!

like image 838
Jie Wu Avatar asked Oct 23 '22 19:10

Jie Wu


1 Answers

You probably need to generate a signature object, which is a bit tricky:

- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector {
    NSMethodSignature *sig = [super methodSignatureForSelector:selector];
    if (!sig) {
        if (selector == @selector(testMessage)) {
            // Create a signature for our fake message.
            sig = [NSMethodSignature signatureWithObjCTypes:"@:"];
        }
    }
    return sig;
}

- (void)forwardInvocation:(NSInvocation *)anInvocation
{
   // Do whatever you want with the invocation.
}

The biggest issue seems to be the argument to signatureWithObjCTypes:. See Apple's type encoding documentation. Every method has at least two arguments: id self (type @) and SEL _cmd (type :).

Another way would be to have a dummy method, say - (void)dummy { } and then use sig = [super methodSignatureForSelector:@selector(dummy)]; to get the signature for your faked method.

like image 57
DarkDust Avatar answered Nov 15 '22 09:11

DarkDust