views:

762

answers:

2

Hello,

I'm wondering if it's possible to have something similar to ActionScript 3's Dictionary object with weak keys in Objective-C. I want to be able to 'attach' an instance of a class to other arbitrary instances.

Example;

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

And later:

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

The tricky part is that after the objected referenced by someObject is dealloc'd, I want the object referenced by meta to be released (and dealloc'd, assuming no client code has retained it).

Possible? I took a look at +[NSValue valueWithNonretainedObject:] but I'm not sure if this is what I want because there when I later query -[NSValue nonretainedObjectValue] it seems like I would get a pointer to garbage (how could NSValue zero the pointer when the object was dealloc'd?).

Thanks,

benjamin

+1  A: 

Are you looking for NSHashMap perhaps? It does zeroing references.

MarkusQ
I'm developing for iPhone and unfortunately NSHashMap doesn't seem to be available.
bvanderveen
+1  A: 

It sounds like what you're asking is the ability to react to a weak-referenced instance variable to be deallocated. You can certainly use the __weak attribute (with GC enabled) to create a weak reference, but there's no built-in mechanism to catch when such an attribute is zeroed after its target is GCed.

If you really want this, your best bet is to use the same mechanism Apple's Key-Value Observing uses: method swizzling. Maintain a global table (such as a NSHashMap or NSMapTable) mapping objects to their corresponding metadata objects, then replace the dealloc/finalize methods in the class of the object you're attaching to with versions that look up the corresponding metadata object in the table and send a message to tear it down. (You also need another table or two that maps classes to their original dealloc/finalize methods.) JRSwizzle provides a nice interface to swizzling.

If you want to to be really fancy, instead of overwriting the dealloc/finalize for all objects of the target class, you can create a proxy class and reassign the isa pointer for just that class, such that there's no performance hit on deallocation for the objects you're not watching. (KVO does this, too.)

Nicholas Riley
Method swizzling sounds pretty straight-forward. Can you elaborate on the isa-swizzling technique you mentioned? As I understand it, that would allow me to effectively change the class of the object, thereby providing a new implementation of <code>dealloc</code>, correct?
bvanderveen
Yes, that's correct.
Nicholas Riley
Also note that in 10.5 there is a function you can use for this, which is preferable going forward: http://developer.apple.com/DOCUMENTATION/Cocoa/Reference/ObjCRuntimeRef/Reference/reference.html#//apple_ref/c/func/object_setClass
Nicholas Riley