views:

25

answers:

1

I tried to figure out this code referencing: http://stackoverflow.com/questions/1187112/cocoa-dictionary-with-enum-keys

+ (NSValue*)valueWithReference:(id)target
{
    return [NSValue valueWithBytes:&target objCType:@encode(id*)];
}

And,

[table setObject:anObject forKey:[NSValue valueWithReference:keyObject]];

But it feels something not good. Any recommendations?

A: 

You're absolutely right it's not good.

For one, you're encoding the wrong type (it should be @encode(id), not @encode(id*)), but in most cases this shouldn't cause a big problem.

The bigger problem is that this completely ignores memory management. The object won't be retained or copied. If some other code releases it, it could just disappear, and then your dictionary key will be a boxed pointer to garbage or even a completely different object. This is basically the world's most advanced dangling pointer.

You have two good options:

  1. You could either add NSCopying to the class or create a copyable subclass.

    • This option will only work for objects that can meaningfully be copied. This is most classes, but not necessarily all (e.g. it might be bad to have multiple objects representing the same input stream)
    • Implementing copying can be a pain even for classes where it makes sense — not difficult, per se, but kind of annoying
  2. You could instead create the dictionary with the CFDictionary API. Since Core Foundation types don't have a generic copy function, CFDictionary just retains its keys by default (though you can customize its behavior however you like). But CFDictionary is also toll-free bridged with NSDictionary, which means that you can just cast a CFDictionaryRef to an NSDictionary* (or NSMutableDictionary*) and then treat it like any other NSDictionary.

    • This means that the object you're using as a key must not change (at least not in a way that affects its hash value) while it's in the dictionary — ensuring this doesn't happen is why NSDictionary normally wants to copy its keys
Chuck
CFDictionary option great! Thanks!
Eonil
If I use `[NSValue valueWithBytes:
Eonil
Chuck