2013-03-06 8 views
7

Wenn ich die folgenden Objekte:Objective-C: Wie übergibt man ein Objekt als Blockargument an eine Methode, die ihre Basisklasse erwartet?

@interface Simple : NSObject 

@end 

@interface Complex : Simple 

@end 

Und ein anderes Objekt wie:

@interface Test : NSObject 

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

@end 

Alles funktioniert, wenn ich die Methode aufrufen, wie:

[Test doSomething:^(Simple * obj) { 

}]; 

Wenn ich stattdessen versuchen, rufen es mag:

[Test doSomething:^(Complex * obj) { 

}]; 

Der Compiler sagt, dass:

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

Da ComplexSimple erstreckt, dachte ich, das funktionieren würde, wie in Java.

Gibt es einen Weg, dies irgendwie zu erreichen?

Antwort

8

Leider ist dies eine Einschränkung der Block API. Wenn Sie möchten, haben Sie die Möglichkeit, völlig Verzicht Typsicherheit und erklärt den Block als:

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

dem Sie die Klasse der Argumente des Blocks festlegen können. Aber wieder ist dies völlig unsicher, typenweise.

+0

Ist das wirklich bedauerlich? 'Test' fragt nach und erhält einen Verweis auf einen Block mit einer Signatur, die besagt, dass der Block ein Argument vom Typ' Simple' akzeptiert. Wenn Sie ihm einen Block mit dem Subtyp "Complex" übergeben, kann dies bedeuten, dass "Test" einen illegalen Aufruf ausführen könnte, indem er den Block mit einer anderen Unterklasse von "Simple" aufruft. –

+0

Ich sage nur, dass es vernünftig erscheint, dies einen Vertragsbruch zu nennen. Wenn dies nicht der Fall ist, kann der Compiler nicht wissen, ob irgendein Aufruf in "Test" zum Ausführen des Blocks einen legalen Parameter aufweist. –

+0

@SeamusCampbell Tut mir leid, ich habe nicht ganz durchgelesen, was du geschrieben hast. Ja genau. – CodaFi

2

Verwenden Sie id anstelle von Complex * oder Simple *. Block-Parameter-Typen werden anders behandelt als Methoden-Parameter-Typen (danke @CodaFi)