Objective c 选择器未由methodSignatureForSelector发送到forwardInvocation

Objective c 选择器未由methodSignatureForSelector发送到forwardInvocation,objective-c,Objective C,为了便于学习,我正在尝试更改对对象调用的方法。 这是我的密码 #import <Foundation/Foundation.h> @interface A : NSObject -(void) say: (NSString*) s; -(NSMethodSignature*) methodSignatureForSelector: (SEL) aSelector; -(void) forwardInvocation: (NSInvocation*) invocation; @end

为了便于学习,我正在尝试更改对对象调用的方法。 这是我的密码

#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;
}
#导入
@接口A:NSObject
-(void)说:(NSString*)s;
-(NSMethodSignature*)方法签名选择器:(SEL)选择器;
-(void)转发调用:(NSInvocation*)调用;
@结束
@实施A
-(void)说:(NSString*)s{
printf(“说\%s\”,[s UTF8String]);
}
-(NSMethodSignature*)方法签名选择器:(SEL)选择器{
返回[A instanceMethodSignatureForSelector:@selector(say:)];
}
-(void)转发调用:(NSInvocation*)调用{
//[调用集合选择器:@selector(say:)];
[调用invokeWithTarget:self];
}
@结束
int main(int args,char*argv[]){
NSAutoreleasePool*池=[[NSAutoreleasePool alloc]init];
A*myObject=[[A alloc]init]autorelease];
[我的对象尝试说:@“你好,奇怪的方法!”;
[池释放];
返回0;
}
我想使用-say:无论尝试在类A的对象上使用哪个方法

结果是一个Segfault。
似乎发送到forwardInvocation的调用对象仍然有@selector(tryToSay:)作为其选择器。它不应该得到在methodSignatureForSelector中设置的相同选择器吗?

不,它不是
NSMethodSignature
不会对选择器进行编码。它对方法的签名进行编码。这意味着参数的类型和数量。它也不能正常工作。如果有人试图调用像
-setInteger:
这样的方法,该方法接受一个整数,它将被传递给您的方法
-say:
,该方法需要一个
NSString*
。但是它不会得到一个
NSString*
,它会得到一个
NSUInteger
,任何试图取消引用的操作都会崩溃(除非它是0)。

那么我想我不明白为什么重写
-methodSignatureForSelector:
如此重要。无论如何谢谢你!如果您不提供方法签名,并且运行时无法找到具有该选择器本身的方法,则它无法首先构造
NSInvocation
。尽管有方法签名,我的示例还是导致崩溃的原因是
NSUInteger
NSString*
都以相同的方式传递到函数中(例如寄存器/堆栈)。问题是,如果将
3
传入,则生成的
-例如:
将尝试将
3
视为对象指针,当取消引用时,它将崩溃。