5

我只是在研究 Objective-C 的“消息转发”。我编写了一个测试程序来验证我是否可以在运行时“吞下”一个无法识别的选择器。所以我这样做了:

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

但它仍然在运行时抛出“无法识别的选择器”错误。搜索解决方案后,我知道我需要重写方法“methodSignatureForSelector:”,所以我编写了另一个名为“Proxy”的代理类和以下方法:

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

但是,实际上,我不想实现这样的另一个代理类来完成这个方法。我想做的就是忽略这个未知的选择器。但是如果我只是输入这个,它就不起作用:

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

所以,我想知道有什么方法可以简单地“吞下”这个错误?(不使用异常处理程序,我想要一种类似“转发”的方式)。谢谢!

4

1 回答 1

3

您可能需要生成一个签名对象,这有点棘手:

- (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.
}

最大的问题似乎是对signatureWithObjCTypes:. 请参阅Apple 的类型编码文档。每个方法至少有两个参数:id self(type @)和SEL _cmd(type :)。

另一种方法是使用一个虚拟方法,例如- (void)dummy { },然后使用它sig = [super methodSignatureForSelector:@selector(dummy)];来获取伪造方法的签名。

于 2011-11-07T11:19:56.873 回答