12

Gibt es in Objective-C Möglichkeiten zur Reflektion, mit denen Sie generische NSCoding-Implementierungen schreiben können, indem Sie die öffentlichen Eigenschaften eines Objekts untersuchen und generische Implementierungen von encodeWithCoder generieren: und initWithCoder:.Objective-C-Reflektion für generische NSCoding-Implementierung

Ich denke an etwas wie XStream für Java, das eine generische Möglichkeit zum Serialisieren und Deserialisieren von Java-Objekten durch Reflektion ermöglicht. Noch besser wäre wahrscheinlich ein Mittel zum Markieren von Eigenschaften als Dinge, die Sie serialisieren möchten oder die transient sind (wie das vorübergehende Schlüsselwort in Java).

Ich habe die Dokumentation über Archives and Serializations Programming Guide für Kakao gelesen. Ich verstehe, dass Sie etwas Kontrolle über die Serialisierung Ihrer Objekte haben wollen, aber es ist im Allgemeinen ein symmetrischer Prozess und es scheint seltsam zu sein, umzukehren, was für die Serialisierung codiert wird, um es zu deserialisieren. Ich glaube an DRY (wiederhole dich nicht).

Antwort

12

Nicht nur ist es möglich, aber ich habe einen Freund, der genau das getan hat. (Sie können seine blog about it here sehen.) Die Reflexion wird mithilfe der Objective-C-Laufzeitfunktionen durchgeführt, die in der Objective-C 2.0 Runtime Reference dokumentiert sind. Schau mal.

Beachten Sie jedoch, dass dies nur funktioniert, wenn Sie das generische Verhalten zum Speichern aller Instanzvariablen verwenden möchten. Möglicherweise möchten Sie nicht, dass ein NSView seine Superansicht speichert. In solchen Fällen würde der generische Fall nicht funktionieren.

Sie könnten zwischen seriellem und nicht seriellem unterscheiden, indem Sie Eigenschaften für alle zu speichernden Instanzvariablen deklarieren und alle anderen Variablen "versteckt" lassen, aber das verdreht den ganzen Zweck der Eigenschaften zu einem kleinen Vorteil. Ich würde es nicht empfehlen.

6

(Ich bin der Autor des Blog-Posts in BJ Homers Kommentar verlinkt). Es gibt einige Vorbehalte bei der Verwendung des Codes:

  1. Die Zielklasse muss KVC-kompatibel sein. Wenn Sie Objective-C 2.0-Eigenschaften für Ihre Ivars verwenden, sind Sie fertig. Andernfalls müssen Sie sicherstellen, dass Ihre Klasse so eingerichtet ist, dass sie ordnungsgemäß auf valueForKey: und setValue: forKey: methods reagiert.
  2. Der Code verwendet ein undokumentiertes "Feature" der Laufzeit, um die ivar-Klassen rekursiv an NSCoding anzupassen. Wenn kompiliert, fast alle Tippinformationen (AFAIK) aus dem Code entfernt wird, noch um die Ivars zu speichern, müssen sie auch NSCoding entsprechen. Ich entdeckte, dass, wenn der ivar ein Objekt ist und ich ivar_getTypeEncoding() darauf anrufe, ich eine c-Zeichenfolge zurückbekomme, die ungefähr wie folgt aussieht: {#IVAR_CLASS} (Beispiel: {#NSString}). Was ich tue, ist die Zeichenfolge zwischen den Zeichen # und} zu erhalten, ein Klassenobjekt mit NSClassFromString zu erstellen und darauf zurückzugreifen.
  3. Dieser Code wird alle Ivars speichern.
  4. Benutzung auf eigene Gefahr (natürlich)

schrieb ich dies in erster Linie als ein Proof of Concept, und es gibt viele Fälle, in denen dieser Code spektakulär scheitern würde. Zum Beispiel, in Objekt A hat einen ivar für B, und B hat einen ivar für A, dann würde die Verwendung des Codes, um den einen oder anderen zu serialisieren, (glaube ich) eine Endlosschleife verursachen.

Nichtsdestotrotz finde ich, dass es ziemlich aufregend ist, dass Objective-C sogar erlaubt, Sachen wie überhaupt zu machen.

0

Check out RMModelObject:

http://www.realmacforge.com/svn/trunk/RMModelObject/

Beachten Sie jedoch, dass ObjC Runtime Sachen in 10.5 funktioniert und in dem Simulator, aber nicht auf einem tatsächlichen iPhone. Habe das auf die harte Tour herausgefunden. Vielleicht unterstützt OS 3.0 es schließlich, aber ich habe es nicht überprüft.

Verwandte Themen