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

私が知る限り、ランタイムは [スパース値] を呼び出すときに SparseClass のインスタンスで forwardInvocation: を呼び出す必要がありますが、完全に無視されます。

-[SparseClass 値]: 認識されないセレクターがインスタンス 0x4b1c4a0 に送信されました *** キャッチされない例外 'NSInvalidArgumentException' によりアプリを終了します。

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;
}

注:の適切な実装については、Jiloc の回答methodSignatureForSelector:を参照してください。

于 2011-01-06T23:20:22.050 に答える