19

我无法让 forwardInvocation 工作。出于某种原因,Objective-C 运行时完全忽略了我的 forwardInvocation: 方法并抛出了一个无法识别的选择器异常。

我的测试代码如下:

@interface InvocationTest : NSObject
{
}

+ (void) runTest;

@end


@interface FullClass: NSObject
{
    int value;
}
@property(readwrite,assign) int value;

@end

@implementation FullClass

@synthesize value;

@end


@interface SparseClass: NSObject
{
}

@end

@implementation SparseClass

- (void)forwardInvocation:(NSInvocation *)forwardedInvocation
{
    NSLog(@"ForawrdInvocation called");

    FullClass* proxy = [[[FullClass alloc] init] autorelease];
    proxy.value = 42;
    [forwardedInvocation invokeWithTarget:proxy];
}

@end


@implementation InvocationTest

+ (void) runTest
{
    SparseClass* sparse = [[[SparseClass alloc] init] autorelease];
    NSLog(@"Value = %d", [sparse value]);
}

@end

我正在处理以下资源中的信息:

http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtForwarding.html#//apple_ref/doc/uid/TP40008048-CH105 http://cocoawithlove.com/2008/ 03/construct-nsinvocation-for-any-message.html

据我所知,当我调用 [sparse value] 时,运行时应该在 SparseClass 的实例上调用 forwardInvocation:,但它被完全忽略:

-[SparseClass 值]:无法识别的选择器发送到实例 0x4b1c4a0 *** 由于未捕获的异常“NSInvalidArgumentException”而终止应用程序,原因:“-[SparseClass 值]:无法识别的选择器发送到实例 0x4b1c4a0”

4

2 回答 2

39

您还必须覆盖- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector才能使其正常工作。

我猜

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
    return [FullClass instanceMethodSignatureForSelector:aSelector];
}

应该可以。

于 2011-01-06T23:19:36.037 回答
26

NSObject文档:

重要提示:要响应对象本身无法识别的方法,methodSignatureForSelector:除了forwardInvocation:. 转发消息的机制使用从中获得的信息methodSignatureForSelector:来创建NSInvocation要转发的对象。您的覆盖方法必须为给定的选择器提供适当的方法签名,或者通过预先制定一个或通过向另一个对象询问一个。

并且,从运行时文档中:

...如果一个对象转发它收到的任何远程消息,它应该有一个版本methodSignatureForSelector:可以返回最终响应转发消息的方法的准确描述;例如,如果一个对象能够将消息转发给它的代理,你可以实现methodSignatureForSelector:如下:

- (NSMethodSignature*)methodSignatureForSelector:(SEL)selector 
{ 
    NSMethodSignature* signature = [super methodSignatureForSelector:selector];
    if (!signature) {
       signature = [surrogate methodSignatureForSelector:selector];
    } 
    return signature;
}

注意:请参阅 Jilouc 的正确实施答案methodSignatureForSelector:

于 2011-01-06T23:20:22.050 回答