2013-03-06 17 views
7

Se ho i seguenti oggetti:Objective-C: come passare un oggetto come argomento di blocco a un metodo che si aspetta la sua classe base?

@interface Simple : NSObject 

@end 

@interface Complex : Simple 

@end 

E un altro oggetto simile:

@interface Test : NSObject 

+(void) doSomething:(void (^)(Simple*)) obj; 

@end 

Tutto funziona se chiamo il metodo simile:

[Test doSomething:^(Simple * obj) { 

}]; 

Quando provo invece a chiamare Mi piace:

[Test doSomething:^(Complex * obj) { 

}]; 

Il compilatore dice che:

Incompatible block pointer types sending 'void (^)(Complex *__strong)' to parameter of type 'void (^)(Simple *__strong)'

Perché Complex estende Simple, ho pensato che questo avrebbe funzionato, come in Java.

C'è un modo per raggiungere questo in qualche modo?

risposta

8

Sfortunatamente, questa è una limitazione dell'API Blocks. Se si desidera, si ha la possibilità di sicurezza di tipo completamente rinuncia e dichiarando il blocco come:

+(void) doSomething:(void (^)(id)) obj; 

che permette di impostare la classe degli argomenti del blocco. Ma ancora una volta, questo è completamente pericoloso, di tipo saggio.

+0

È davvero sfortunato? 'Test' chiede e ottiene un riferimento a un blocco con una firma che dice che il blocco accetta un argomento di tipo' Semplice'. Consegnargli un blocco che prende un sottotipo 'Complesso' potrebbe significare che' Test' potrebbe effettuare una chiamata illegale chiamando il blocco con una sottoclasse diversa di 'Semplice'. –

+0

Sto solo dicendo che sembra ragionevole chiamare questa una violazione del contratto. Se non lo è, il compilatore non può sapere se una chiamata in 'Test' per eseguire il blocco ha un parametro legale. –

+0

@SeamusCampbell Spiacente, non ho letto abbastanza di ciò che hai scritto. Si, esattamente. – CodaFi

2

Utilizzare id anziché Complex * o Simple *. I tipi di parametri di blocco vengono gestiti in modo diverso rispetto ai tipi di parametri del metodo (grazie @CodaFi)

Problemi correlati