selector not sent by methodSignatureForSelector to forwardInvocation
I'm trying to change which method is called on an object for the sake of learning. Here is my code.
#import <Foundation/Foundation.h>
@interface A : NSObject
-(void) say: (NSString*) s;
-(NSMethodSignature*) methodSignatureForSelector: (SEL) aSelector;
-(void) forwardInvocation: (NSInvocation*) invocation;
@end
@implementation A
-(void) say: (NSString*) s {
printf( "say \"%s\"", [s UTF8String] );
}
-(NSMethodSignature*) methodSignatureForSelector: (SEL) aSelector {
return [A instanceMethodSignatureForSelector: @selector(say:)];
}
-(void) forwardInvocation: (NSInvocation*) invocation {
// [invocation setSelector:@selector(say:)];
[invocation invokeWithTarget:self];
}
@end
int main(int args, char* argv[]){
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
A* myObject = [[[A alloc] init] autorelease];
[myObject tryToSay:@"Hello strange method!开发者_运维技巧"];
[pool release];
return 0;
}
I want to use -say: no matter which method is attempted used on objects of the class A.
The result is a Segfault. It seems the invocation object sent to forwardInvocation still has @selector(tryToSay:) as its selector. Is it not supposed to get the same selector that was set in methodSignatureForSelector?
No, it's not. NSMethodSignature
doesn't encode the selector. It encodes the signature of the method instead. This means things like the type and number of arguments. It's also not going to work correctly. If someone tries to invoke a method like -setInteger:
which takes an NSUInteger, it will be passed to your method -say:
which is expecting an NSString*
. But it won't get an NSString*
, it will get an NSUInteger
, and any attempt to dereference that will crash (unless it's 0).
精彩评论