Objective-C Metaprogrammierung: Blöcke zu Methoden

written by Martin Häcker on

Die Ruby Welt verwendet Blöcke (Closures) liebend gerne für alles mögliche. Zum Beispiel als Builder-Methapher um Baumstrukturen (XML, GUI's, HTML, Tests) in der Sprache hinzuschreiben und dann nur noch in die Target-Sprache zu rendern.

Das sieht in Tests zum Beispiel so aus:

describe "something" do

  it "should do fnord" do
    someObject.should be_fnordy
  end

end

Der Trick dabei ist das alles von do bis end jeweils ein Block ist der von der Methode describe oder it dann in eine UnitTest Klassenstruktur eingehängt wird um dann später als 'ganz normale' unit tests ausgeführt zu werden.

Jetzt wo Objective-C auch Blöcke unterstützt (ok, die können natürlich weniger als das Ruby Equivalent) müsste das eigenltich auch gehen - und siehe da mit Cedar gibt es auch schon einen ersten Versuch RSpec in Objective-C nachzubauen.

Well und daher habe ich mir mal angeschaut wie weit man denn kommt wenn man in Objective-C einen Block in eine Instanz-Methode umwandeln will.

Gleich vorneweg - das Typ-System von Objective-C macht mir hier einen kleinen Strich durch die Rechnung - ich habe es nicht geschafft einen Block nicht direkt als Funktions-pointer verwenden.

Aber mit etwas Umweg geht es doch.

Der Trick ist das Blöcke auch id's sein können, d.h. man kann sie bequem in ein NSMutableDictionary packen.

Also brauche ich auf meiner Klasse nur ein Dictionary, speichere die Blöcke darin mit dem Namen der Methode ab und baue mir einen generischen Dispatcher-IMP der den Selector (zweites unsichtbares Argument jeder Objective-C Methode) verwendet um den Block aus aus dem Dictionary zu ziehen und führe ihn dann einfach aus.

[source:/open-source/adding-blocks-as-methods/trunk/AttachBlocksAsMethods.m So sieht dass dann aus]