2011-04-07 20 views
10

Non capisco perché dobbiamo chiamare il metodo setSelector sugli oggetti NSInvocation quando tali informazioni sono già passate tramite invocationWithMethodSignature.Qual è lo scopo del metodo setSelector nella classe NSInvocation?

Per creare un oggetto NSInvocation facciamo la seguente:

SEL someSelector; 
NSMethodSignature *signature; 
NSInvocation *invocation; 

someSelector = @selector(sayHelloWithString:); 

//Here we use the selector to create the signature 
signature = [SomeObject instanceMethodSignatureForSelector:someSelector]; 
invocation = [NSInvocation invocationWithMethodSignature:signature]; 

//Here, we again set the same selector 
[invocation setSelector:someSelector]; 
[invocation setTarget:someObjectInstance]; 
[invocation setArgument:@"Loving C" atIndex:2]; 

noti che abbiamo passato il selettore [SomeObject instanceMethodSignatureForSelector: someSelector]; e di nuovo a [invocation setSelector:someSelector];.

C'è qualcosa che mi manca?

+1

+1 - È bello vedere qui una domanda che non è stata posta (e risposta) già un milione di volte, e non è scritta in un gergo istantaneo indecifrabile. :-) –

+0

Un piccolo punto: 'signature = [SomeObject instanceMethodSignatureForSelector: someSelector];' dovrebbe essere sia 'signature = [[SomeObject class] instanceMethodSignatureForSelector: someSelector]; o signature = [SomeObject methodSignatureForSelector: someSelector]; ' – Brynjar

risposta

8

Una firma non è un selettore. Un selettore è il nome di un messaggio. La firma definisce i parametri e il valore di ritorno. Puoi avere molti selettori con la stessa firma e viceversa. Se guardi allo NSMethodSignature, noterai che non esiste un metodo -selector; le firme non portano in giro un determinato selettore.

Si consideri il seguente

- (void)setLocation:(CGFloat)aLocation; 
- (void)setLocation:(MyLocation*)aLocation; 

Hanno lo stesso selettore @selector(setLocation:), ma firme diverse.

- (void)setX:(CGFloat)x; 
- (void)setY:(CGFloat)y; 

Questi hanno la stessa firma, ma diversi selettori.

Selectors dal linguaggio di programmazione ObjC può essere un utile riferimento per la comprensione di questo.

+0

Mentre ottengo quello che dici, sembra esserci un po 'di ridondanza nella lingua. Sto impostando il selettore due volte (una volta nella firma e ancora una volta nell'istanza di invocazione). Io personalmente (IMHO) penso che sarebbe più efficiente derivare il selettore (che nel mio caso era definito in 'someSelector') dalla firma. – haroldcampbell

+0

Non è possibile derivare un selettore da una firma. È possibile ricavare una firma da una destinazione e un selettore chiedendo al target (ricordare, è possibile creare nuovi metodi e classi in fase di esecuzione, non è possibile determinare nulla di ciò in fase di compilazione).Hai ragione che potrebbe esserci '+ invocationWithTarget: selector: arguments:' metodo di scelta rapida (il mio team ha una categoria che aggiunge qualcosa di simile). Non sarebbe più efficiente dato che chiamerebbe semplicemente il codice che stai chiamando, ma sarebbe un po 'più conveniente. –

3

Una firma del metodo definisce solo il tipo restituito e il numero e il tipo di argomenti. Non include nulla sul nome del selettore. Ad esempio, tutti questi metodi hanno la stessa firma, pur avendo selettori diversi:

-(void) foo:(NSString*)fooString; 
-(void) bar:(NSString*)barString; 
-(void) baz:(NSString*)bazString; 
0

Questa è una specie di side-risposta, ma il fatto che si può fare la seguente mi ha aiutato a capire meglio la separazione tra il metodo firme e selettori.

Questo codice è all'interno di una View Controller

NSMethodSignature *sig = nil; 
sig = [[self class] instanceMethodSignatureForSelector:@selector(viewDidAppear:)]; 
NSInvocation *myInvocation = nil; 
myInvocation = [NSInvocation invocationWithMethodSignature:sig]; 

[myInvocation setTarget:_somePopoverController]; 
[myInvocation setSelector:@selector(dismissPopoverAnimated:)]; 
BOOL animate = YES; 
[myInvocation setArgument:&animate atIndex:2]; 
[myInvocation invoke]; 

Dal momento del UIViewController viewDidAppear: e di UIPopoverController dismissPopoverAnimated: entrambi prendono un argomento BOOL e tornare vuoto, è possibile creare la firma del metodo utilizzando un selettore, ma inviare l'invocazione ad un altro.

Problemi correlati