2011-11-07 13 views
5

Sto studiando il "forwarding del messaggio" di Objective-C. Scrivo un programma di test per verificare se posso "inghiottire" un selettore non riconosciuto in fase di esecuzione. Quindi ho fatto questo:Come posso "inghiottire" l'errore "selettore non riconosciuto" inoltrando i messaggi?

- (void) forwardInvocation: (NSInvocation *) anInvocation { 
    if ([anInvocation selector] == @selector(testMessage)){ 
     NSLog(@"Unknow message"); 
    } 
    return; 
} 

Ma getta ancora l'errore "non riconosciuto selettore" in fase di esecuzione. Dopo la ricerca la risoluzione so che ho bisogno di ignorare il metodo "methodSignatureForSelector:", quindi scrivo un'altra classe proxy chiamato "Proxy" e il seguente metodo:

(NSMethodSignature *)methodSignatureForSelector:(SEL)selector { 
    if ([Proxy instancesRespondToSelector: selector]) { 
     return [Proxy instanceMethodSignatureForSelector: selector]; 
    } 
    return [super methodSignatureForSelector:selector]; 
} 

Ma, in realtà, non voglio implementare tale altra classe proxy per realizzare questo metodo. Tutto quello che voglio fare è ignorare questo selettore sconosciuto. Ma se mi basta digitare questo, non funziona:

(NSMethodSignature *)methodSignatureForSelector:(SEL)selector { 
    return [super methodSignatureForSelector:selector]; 
} 

Quindi, mi chiedo c'è alcun modo che possa semplicemente "ingoiare" questo errore? (Non utilizzo gestore di eccezioni, voglio un modo "forwarding" -like). Grazie!

+0

Cfr. http://stackoverflow.com/a/11531609/ –

risposta

3

probabilmente avete bisogno per generare un oggetto di firma, che è un po 'complicato:

- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector { 
    NSMethodSignature *sig = [super methodSignatureForSelector:selector]; 
    if (!sig) { 
     if (selector == @selector(testMessage)) { 
      // Create a signature for our fake message. 
      sig = [NSMethodSignature signatureWithObjCTypes:"@:"]; 
     } 
    } 
    return sig; 
} 

- (void)forwardInvocation:(NSInvocation *)anInvocation 
{ 
    // Do whatever you want with the invocation. 
} 

Il problema più grande sembra essere l'argomento signatureWithObjCTypes:. Vedi Apple's type encoding documentation. Ogni metodo ha almeno due argomenti: id self (tipo @) e SEL _cmd (tipo :).

Un altro modo sarebbe avere un metodo fittizio, ad esempio - (void)dummy { } e quindi utilizzare sig = [super methodSignatureForSelector:@selector(dummy)]; per ottenere la firma per il metodo simulato.

+0

Funziona! Grazie! Ma un'altra cosa: se seguo il tuo suggerimento e provo a fare una tale chiamata: [un selettore di chiamata] in forwardInvocation: metodo, si verifica l'errore: ** Termina l'app a causa dell'eccezione non rilevata 'NSInvalidArgumentException', motivo: '- [NSInvocation getArgument : atIndex:]: index (1) out of bounds [-1, 0] '**, Perché? –

+3

Ho trovato [questo] (http://www.cocoabuilder.com/archive/cocoa/289799-nsproxy-nsinvocation-question.html): * La documentazione di [NSMethodSignature signatureWithObjTypes:] è errata. Il primo elemento nell'array di tipi è il tipo restituito, non l'id o il tipo di classe, che in effetti mi ha lasciato un'istanza MSMethodSignature che non contiene alcun tipo di argomento per il parametro selector. * Ciò probabilmente significa che per un metodo '- (void) foo' è necessario il tipo '" v @: "' nell'argomento di 'signatureWithObjCTypes:'. – DarkDust

+0

umm ... Capisco ... Grazie !! –

Problemi correlati