未调用forwardInvocation?

发布于 2024-10-10 22:27:46 字数 1678 浏览 4 评论 0原文

我在使forwardIncallation 正常工作时遇到问题。由于某种原因,Objective-C 运行时完全忽略我的forwardInitation: 方法并抛出无法识别的选择器异常。

我的测试代码如下:

@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-nsinvocau -for-any-message.html

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

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

I'm having trouble getting forwardInvocation to work. For some reason, the Objective-C runtime completely ignores my forwardInvocation: method and throws an unrecognized selector exception.

My test code is as follows:

@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

I'm working off information from the following resources:

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

As far as I can tell, the runtime should be calling forwardInvocation: on the instance of SparseClass when I invoke [sparse value], but it gets completely ignored:

-[SparseClass value]: unrecognized selector sent to instance 0x4b1c4a0
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[SparseClass value]: unrecognized selector sent to instance 0x4b1c4a0'

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

肤浅与狂妄 2024-10-17 22:27:46

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

我想

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

应该没问题。

You also have to override - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector to get it working.

I guess

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

should be ok.

懵少女 2024-10-17 22:27:46

来自 NSObject 文档:

重要提示:要响应对象本身无法识别的方法,除了 forwardInitation: 之外,您还必须重写 methodSignatureForSelector:。转发消息的机制使用从 methodSignatureForSelector: 获取的信息来创建要转发的 NSInitation 对象。您的重写方法必须为给定的选择器提供适当的方法签名,可以通过预先制定一个方法签名,也可以通过向另一个对象请求一个方法签名。

并且,来自 运行时文档:

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

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

注意: 请参阅 Jilouc 的 回答,以正确实现 methodSignatureForSelector:

From the NSObject documentation:

Important: To respond to methods that your object does not itself recognize, you must override methodSignatureForSelector: in addition to forwardInvocation:. The mechanism for forwarding messages uses information obtained from methodSignatureForSelector: to create the NSInvocation object to be forwarded. Your overriding method must provide an appropriate method signature for the given selector, either by preformulating one or by asking another object for one.

And, from the runtime documentation:

... if an object forwards any remote messages it receives, it should have a version of methodSignatureForSelector: that can return accurate descriptions of the methods that ultimately respond to the forwarded messages; for example, if an object is able to forward a message to its surrogate, you would implement methodSignatureForSelector: as follows:

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

Note: See Jilouc's answer for the proper implementation of methodSignatureForSelector:.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文