Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Weak-keyed dictionary in Objective-C

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

Update 23 September 2011: I believe the way to do this is with objc_setAssociatedObject and related functions. See the Objective-C Runtime Reference.

like image 432
bvanderveen Avatar asked Dec 06 '25 15:12

bvanderveen


1 Answers

It sounds like what you're asking for is the ability to react to a weak-referenced instance variable being 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.)

like image 176
Nicholas Riley Avatar answered Dec 08 '25 10:12

Nicholas Riley



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!