2009-04-09 7 views
3

Je me demande s'il est possible d'avoir quelque chose de similaire à l'objet Dictionary d'ActionScript 3 avec des touches faibles dans Objective-C. Je veux pouvoir "attacher" une instance d'une classe à d'autres instances arbitraires.Dictionnaires faibles en Objective-C

Exemple;

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

Et plus tard:

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

La partie délicate est que, après l'objet de l'opposition référencée par someObject est dealloc'd, je veux l'objet référencé par meta à être libéré (et dealloc'd, en supposant aucun code client ne l'a retenu).

Possible? J'ai jeté un coup d'oeil à +[NSValue valueWithNonretainedObject:] mais je ne suis pas sûr si c'est ce que je veux parce que là quand je questionnerai plus tard -[NSValue nonretainedObjectValue] il semblerait que j'obtiendrais un pointeur à la poubelle (comment NSValue pourrait-il zéro le pointeur quand l'objet a été dealloc'd?).

Merci,

benjamin

mise à jour 23 Septembre 2011: Je crois que la façon de le faire est avec objc_setAssociatedObject et fonctions connexes. Voir le Objective-C Runtime Reference.

Répondre

4

Il semble que ce que vous demandez est la capacité de réagir à une variable d'instance référencée faible qui est désallouée. Vous pouvez certainement utiliser l'attribut __weak (avec GC activé) pour créer une référence faible, mais il n'y a pas de mécanisme intégré à attraper quand un tel attribut est mis à zéro après que sa cible soit GCed.

Si vous voulez vraiment cela, votre meilleur pari est d'utiliser le même mécanisme qu'utilise Key-Value Observing d'Apple: la méthode swizzling. Maintenir une table globale (par exemple NSHashMap ou NSMapTable) mappage des objets à leurs objets de métadonnées correspondants, puis remplacer les méthodes dealloc/finalize dans la classe de l'objet auquel vous attachez des versions qui recherchent l'objet de métadonnées correspondant dans la table et envoyer un message pour le démolir. (Vous avez également besoin d'une autre table ou deux qui mappe les classes à leurs méthodes d'origine dealloc/finalize.) JRSwizzle fournit une interface agréable à swizzling.

Si vous voulez être vraiment de fantaisie, au lieu d'écraser le dealloc/finalize pour tous les objets de la classe cible, vous pouvez créer une classe proxy et réassigner le pointeur isa juste pour cette classe, de sorte qu'il n'y a pas de perte de performance sur deallocation pour les objets que vous ne regardez pas. (KVO fait cela aussi.)

+0

Méthode swizzling semble assez simple. Pouvez-vous développer la technique isa-swizzling dont vous avez parlé? Si je comprends bien, cela me permettrait de changer efficacement la classe de l'objet, fournissant ainsi une nouvelle implémentation de dealloc, correct? – bvanderveen

+0

Oui, c'est correct. –

+0

Notez également que dans 10.5 il y a une fonction que vous pouvez utiliser pour cela, ce qui est préférable à l'avenir: http://developer.apple.com/DOCUMENTATION/Cocoa/Reference/ObjCRuntimeRef/Reference/reference.html#//apple_ref/ c/func/object_setClass –

1

Vous cherchez NSHashMap peut-être? Il fait la réduction à zéro des références.

+0

Je suis en train de développer pour iPhone et malheureusement NSHashMap ne semble pas être disponible. – bvanderveen

Questions connexes