2011-01-06 31 views
19

Ho problemi a inoltrare l'installazione al lavoro. Per qualche ragione, il runtime Objective-C ignora completamente il mio metodo forwardInvocation: e lancia un'eccezione selettore non riconosciuta.forwardInvocation non viene chiamato?

mio codice di prova è la seguente:

@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 

sto lavorando fuori informazioni dalle seguenti risorse:

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

Per quanto posso dire, il runtime dovrebbe si chiama forwardInvocation: sull'istanza di SparseClass quando invoco [sparse value], ma viene completamente ignorato:

- [valore SparseClass]: selettore non riconosciuto inviato ad esempio 0x4b1c4a0 *** terminazione app causa eccezione non identificata 'NSInvalidArgumentException', motivo: '- [value SparseClass]: selettore non riconosciuto inviato ad esempio 0x4b1c4a0'

risposta

36

È inoltre necessario eseguire l'override di - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector per farlo funzionare.

immagino

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

dovrebbe essere ok.

+1

Fantastico! Ha funzionato come un fascino. – Karl

24

Dalla documentazione NSObject:

Importante: Per rispondere a metodi che l'oggetto non si riconosce, è necessario eseguire l'override methodSignatureForSelector: oltre a forwardInvocation:. Il meccanismo di inoltro dei messaggi utilizza le informazioni ottenute da methodSignatureForSelector: per creare l'oggetto NSInvocation da inoltrare. Il metodo di override deve fornire una firma di metodo appropriata per il selettore dato, preformando uno o richiedendo un altro oggetto per uno.

E, dalla documentazione runtime:

... se un oggetto inoltra eventuali messaggi remoti che riceve, si dovrebbe avere una versione di methodSignatureForSelector: che può restituire descrizioni accurate dei metodi che alla fine rispondono ai messaggi inoltrati; per esempio, se un oggetto è in grado di inoltrare un messaggio al suo surrogato, si dovrebbe implementare methodSignatureForSelector: come segue:

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

Nota: Sede di answer per la corretta attuazione della methodSignatureForSelector: Jilouc.

+13

Penso che i documenti della Guida di programmazione runtime di Apple non funzionino correttamente. Nella sezione "Inoltro" non menzionano nulla riguardo alla necessità di 'methodSignatureForSelector:' con 'forwardInvocation:'. Per trovare il bocconcino, scorri verso il basso 3 sezioni per scoprire che è necessario implementare un metodo di sezione. – DBD

Problemi correlati