Erstellen eines IMP von einem Objective-C-Block
Frage
Der IMP
Typ in Objective-C stellt einen Funktionszeiger, so weit ich als verstehen. Gibt es eine Möglichkeit, um eine IMP
aus einem Block Zeiger zu machen? Vielen Dank für Ihre Ideen.
Lösung
Da dies geschrieben wurde, gibt es jetzt API in iOS und Mac OS X, die direkt Blocks werden verwandelte sich in IMPs können. Ich schrieb auf einen Weblog Beitrag beschreibt die API (imp_implementationWithBlock ()).
Ein Block ist effektiv eine Struktur, die ein wenig von Metadaten enthält, eine Referenz auf den Code innerhalb des Blocks und eine Kopie der const kopierten Daten innerhalb des Blocks erfasst enthalten sind.
So, nein, gibt es keine Möglichkeit, direkt zwischen einer IMP
und einer Block-Referenzkarte.
Wenn zu einem Block einen Anruf zusammengestellt ist, gibt der Compiler ein Trampolin, das den Stapelrahmen einrichtet und springt dann auf den Programmcode innerhalb des Blocks.
Was Sie tun können, obwohl, ist einen IMP zu schaffen, wie das Trampolin fungiert. Für die folgenden, müssen Sie eine bestimmte IMP für jeden Satz von Argumenten und Rückgabetypen aufgerufen werden. Wenn Sie diese generische machen müssen, müssen Sie Montage verwenden.
Dazu Ich gründe einzigartige Blockinstanzen pro Instanz der Klasse auf. Wenn Sie einen generischen Block haben wollen, die über alle Instanzen hinweg wirkt, bauen einen Hash SEL
-.> Block pro Klasse
(1) assoziierte Blöcke als IMPs wirken, um die zugehörigen Referenzen Mechanismus. So etwas wie:
void (^implementingBlock)(id s, SEL _c, int v) = ^(id s, SEL _c, int v) {
// do something here
}
objc_setAssociatedObject(obj, SELToImp, [implementingBlock copy]));
(2) führen ein Trampolin IMP etwas wie folgt aus:
void void_id_sel_intTramp(id self, SEL _cmd, int value) {
int (^block)(id s, SEL _c, int v) = objc_getAssociatedObject(self, _cmd);
block(self, _cmd, value);
}
(3) stopfen das oben Trampolin in für jeden Wähler über die Objective-C-Laufzeit des API (siehe method_setImplementation
und dergleichen)
Caveats:
-
Dieses wurde in Stackoverflow getippt. Der eigentliche Code wird ähnlich sein, aber wahrscheinlich etwas anders aus.
-
die [implementingBlock Kopie] ist von entscheidender Bedeutung; Blöcke beginnen Leben auf dem Stapel (in der Regel)
Andere Tipps
ich glaube, Mike Ash, mit etwas Hilfe von Landon Fuller, das für den allgemeinen Fall gelöst hat, einschließlich iOS, das härter ist. Er hat eine Klasse auf Github , die einen Block in einen Funktionszeiger drehen wird.
Sie können auch die Ankündigung verleihen und einige interessante Follow-up-Diskussion über Kakao-ungebunden.
UPDATE:. Und jetzt ist es imp_implementationWithBlock()
gemäß oben