2009-04-09 8 views
3

Ich frage mich, ob es möglich ist, etwas ähnliches ActionScript 3 Dictionary Objekt mit schwachen Schlüsseln in Objective-C zu haben. Ich möchte in der Lage sein, eine Instanz einer Klasse an andere beliebige Instanzen anzuhängen.Weak-Keyed-Wörterbuch in Objective-C

Beispiel;

MetaData *meta = [MetaData metaDataForObject:someObject]; 
meta.whatever = foo; 

Und später:

foo = [MetaData metaDataForObject:someObject].whatever; 
[foo doStuff]; 

Der schwierige Teil ist, dass nach dem von someObject verweist widersprochen wird dealloc'd, ich will das Objekt durch meta verwiesen freigegeben (und dealloc'd wird, unter der Annahme, kein Client-Code hat es beibehalten).

Möglich? Ich habe einen Blick auf +[NSValue valueWithNonretainedObject:], aber ich bin mir nicht sicher, ob das ist, was ich will, da dort, wenn ich später Abfrage -[NSValue nonretainedObjectValue] es scheint, wie ich einen Zeiger auf Müll bekommen würde (wie konnte NSValue den Zeiger Null, wenn das Objekt dealloc'd wurde?).

Danke,

benjamin

Update 23. September 2011: Ich glaube, die Art und Weise dies mit objc_setAssociatedObject und verwandten Funktionen zu tun. Siehe Objective-C Runtime Reference.

Antwort

4

Es klingt nach dem, was Sie fordern, ist die Fähigkeit, auf eine auf eine Variable mit geringem Bezug bezogene Instanzvariable zu reagieren. Sie können sicherlich das Attribut __weak (mit aktiviertem GC) verwenden, um eine schwache Referenz zu erstellen, aber es gibt keinen eingebauten Mechanismus, der abgefangen wird, wenn ein solches Attribut auf Null gesetzt wird, nachdem das Ziel auf GCed gesetzt wurde.

Wenn Sie dies wirklich wollen, ist Ihre beste Wette, den gleichen Mechanismus Apples Key-Value Observing zu verwenden: Methode Swizzling. Pflegen Sie eine globale Tabelle (z. B. NSHashMap oder NSMapTable), ordnen Sie Objekte ihren entsprechenden Metadatenobjekten zu und ersetzen Sie dann die dealloc/finalize Methoden in der Klasse des Objekts, mit dem Sie verknüpft sind, mit Versionen, die das entsprechende Metadatenobjekt in der Tabelle suchen und senden Sie eine Nachricht, um es zu zerreißen. (Sie benötigen auch eine andere Tabelle oder zwei, die Klassen auf ihre ursprünglichen dealloc/finalize Methoden abbildet.) JRSwizzle bietet eine nette Schnittstelle zum Swizzling.

Wenn Sie wirklich Lust sein wollen, anstatt die Klasse dealloc/finalize für alle Objekte des Ziels überschreiben, können Sie eine Proxy-Klasse erstellen und zuweisen die isa Zeiger nur für diese Klasse, so dass es keine Performance-Einbußen Freigabe für die Objekte, die Sie nicht beobachten. (KVO tut das auch.)

+0

Methode Swizzling klingt ziemlich geradlinig. Können Sie die von Ihnen erwähnte Isa-Swizzling-Technik näher erläutern? So wie ich es verstehe, würde es mir erlauben, die Klasse des Objekts effektiv zu ändern, wodurch eine neue Implementierung von dealloc, korrekt? – bvanderveen

+0

Ja, das ist richtig. –

+0

Beachten Sie auch, dass es in 10.5 eine Funktion gibt, die Sie für diese Funktion verwenden können, die in Zukunft bevorzugt wird: http://developer.apple.com/DOCUMENTATION/Cocoa/Reference/ObjCRuntimeRef/Reference/reference.html#//apple_ref/ c/func/Objektgruppe –

1

Suchen Sie nach NSHashMap vielleicht? Es führt Referenzen auf Null.

+0

Ich entwickle für iPhone und leider scheint NSHashMap nicht verfügbar zu sein. – bvanderveen

Verwandte Themen