What about using CFDictionary ? You can create a dicitonary with a callback that support address (NULL for example).

I'll echo this; it's a really handy technique that I use frequently (you can even use integers as keys!).

WARNING: Just in case, there is a major warning here. You should avoid NS/CF bridge when inserting/removing value in a dictionary as the semantic is not the same. NSDictionary always try to copy the key whatever the calback is (or at least did it the last time I try).

Right, -[NSDictionary setObject:forKey:] on a CFDictionary created with a custom retain callback will invoke copyWithZone: before calling your retain callback. Apple claims this is not a bug. Getting/removing values with objectForKey:/removeObjectForKey: should work, though; if it doesn't, I'd like to know.


Yes, accessing and removing keys should work fine. For immutable keys (you weren't planning on changing a key behind NSDictionary's back anyway, right) a copy is often just implemented as a retain. Since toll-free bridged NSDictionary must provide CFDictionary retain/ release callbacks to work right on the Core Foundation side of things, it must be copying the key, adding it to the array (where it is retained by the callback), and then releasing it's local reference. Take out steps one and three, which are equivalent to a retain followed by a release, and nothing should change as far as object accessing or removal.

While for new code in Leopard+ apps you might want to look into NSMapTable with the flags Mike suggested, I just was dealing with NSMutableDictionary's key copying off-list last night and didn't see that suggestion. What I did is just added a category on NSMutableDictionary:

@interface NSMutableDictionary (TLMutableDictionaryNoncopiedKeys)
- (void)setObject:(id)anObject forUncopiedKey:(id)aKey;
@end

@implementation NSMutableDictionary (TLMutableDictionaryNoncopiedKeys)

/* NSMutableDictionary copies its keys. When we use pointer-equality for certain types' comparision, this breaks those types' keys. Fortunately, CFMutableDictionary does not assume NSString-ish keys, and the copying behaviour is implemented within the - [NSMutableDictionary addObject:forKey:] method itself (see http://www.cocoabuilder.com/archive/message/cocoa/2008/4/2/203028 and links
 for details).
If we just bridge to Core Foundation when adding keys, everything else should work properly.
 */

- (void)setObject:(id)anObject forUncopiedKey:(id)aKey {
        CFMutableDictionaryRef selfCF = (CFMutableDictionaryRef)self;
        Boolean keyAlreadySet = CFDictionaryContainsKey(selfCF, aKey);
        if (keyAlreadySet) {
                CFDictionaryReplaceValue(selfCF, aKey, anObject);
        }
        else {
                CFDictionaryAddValue(selfCF, aKey, anObject);
        }
}

@end


Replacing this single method was enough for me, since in most cases in my code where the "stringish" (that is, assuming copied keys will still compare equal) behaviour is not desirable, I am creating an empty dictionary and populating it with just that one method. Otherwise, many other methods (especially NSDictionary's initializers and convenience initializers) would all need "uncopiedKey" overrides, and some of these could theoretically end up being much less efficient than the methods they replaced. However, if you can't use just the above method to insert keys, then other solutions like CFDictionary and NSMapTable (especially) might not work much better for you anyway...so this seems like a pretty decent solution for many cases.

hope this helps,
-natevw
_______________________________________________

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]

Reply via email to