2011-01-06 26 views
19

Mam problem z pobraniem funkcji Przekierowanie do pracy. Z jakiegoś powodu środowisko wykonawcze Objective-C całkowicie ignoruje moją metodę forwardInvocation: i zgłasza nierozpoznany wyjątek selektora.forwardInvocation nie jest wywoływana?

Mój kod testu jest następująca:

@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 

pracuję od informacji z następujących źródeł:

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

O ile mogę powiedzieć, że środowisko wykonawcze powinny be call forwardInvocation: na instancji SparseClass po wywołaniu [rzadka wartość], ale zostaje całkowicie zignorowana:

- [SparseClass stosunek] Przełącznik nierozpoznane wysyłane do przykładu 0x4b1c4a0 *** zakończenie aplikacji ze względu nieprzechwyconego wyjątku 'NSInvalidArgumentException' powodu: - [SparseClass stosunek] Przełącznik nierozpoznane wysłany do instancji 0x4b1c4a0 '

Odpowiedz

36

Musisz również zastąpić - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector, aby działało.

Chyba

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

powinno być ok.

+1

Awesome! Pracował jak urok. – Karl

24

Z dokumentacji NSObject:

Ważne: Aby odpowiedzieć na metodach, że obiekt nie sama rozpoznać, trzeba zastąpić methodSignatureForSelector: oprócz forwardInvocation:. Mechanizm przekazywania wiadomości korzysta z informacji uzyskanych z methodSignatureForSelector:, aby utworzyć obiekt, który ma zostać przekazany. Twoja nadpisująca metoda musi dostarczyć odpowiednią sygnaturę metody dla danego selektora, albo przez preformulację, albo przez zapytanie innego obiektu o jeden.

A z dokumentacji runtime:

... jeśli obiekt przekazuje żadnych zdalnych wiadomości, które otrzymał, powinien on mieć wersję methodSignatureForSelector: że może powrócić dokładne opisy metod, które ostatecznie odpowiadają do przesłanych wiadomości; Na przykład, jeśli obiekt jest w stanie przekazać wiadomość do jej surogat, by wdrożyć methodSignatureForSelector: następująco:

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

Uwaga: See Jilouc na answer dla prawidłowej realizacji methodSignatureForSelector:.

+13

Wydaje mi się, że dokumentacja oprogramowania Apple Runtime Programming Guide nie zawiera informacji o tym problemie. W sekcji "Przekazywanie" nie wspominają nic o potrzebie 'methodSignatureForSelector:' z 'forwardInvocation:'. Aby znaleźć ten smakołyk, przewiń 3 sekcje w dół, aby dowiedzieć się, jak zaimplementować metodę sekcji. – DBD

Powiązane problemy