tags:

views:

236

answers:

3

I'm trying to create an NSDictionary that stores objects with keys based on IDs. I know I can use NSNumber objects, but why can't I just use an int instead? Is there some class that supports this? Something like an NSSet almost works, except I can't access it by it's hash value (I've overridden - (NSUInteger) hash to return the object's ID, which always unique)

I'm basically trying to turn this:

//objects is an NSMutableDictionary
- (id) objectForId:(NSUInteger)id {
  return [objects objectForKey:[NSNumber numberWithInt:id]];
}
- (void) addObject:(Object *)foo {
  [objects setObject:foo forKey:[NSNumber numberWithInt:id]];
}

into this:

//objects is an NSSet
- (id) objectForId:(NSUInteger)id {
  return [objects objectForHash:id];
}
- (void) addObject:(Object *)foo {
  [objects addObject:foo];
}
A: 

NSDictionary's setObject:forKey: already takes the key by id, which is what it looks like you're doing with your NSSet equivalent. What about NSDictionary is insufficient for your purposes?

fbrereto
+6  A: 

You'll want to use the C API to NSMapTable after configuring an NSMapTable instance to use integer keys. An example:

#import <Foundation/Foundation.h>

int main (int argc, const char * argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

    NSMapTable *mt = [NSMapTable mapTableWithKeyOptions: NSPointerFunctionsIntegerPersonality | NSPointerFunctionsOpaqueMemory
                                           valueOptions: NSPointerFunctionsObjectPersonality];

    for(NSUInteger i = 0; i<10; i++) 
        NSMapInsert(mt, (void *) i, [NSNumber numberWithInt: i]);

    for(NSUInteger j = 0; j<10; j++)
        NSLog(@"retrieved %@", (id) NSMapGet(mt, (void *) j));

    [pool drain];
    return 0;
}

Note that there appears to be a bug in NSMapTable() where it does not allow 0 to be a key. Oops.

Better documentation of the functional API to NSMapTable is requested in <rdar://problem/7228605>.

A fix for the 0 key problem is documented in <rdar://problem/7228618>

bbum
Does this class exist in the iPhone API?
Ed Marty
Unfortunately, it is not. But you could use CFDictionary, I believe (Pretty sure -- but haven't completed the thought exercise to say 100% for sure).
bbum
+1  A: 

I ended up creating a category on NSDictionary to store objects based on int keys:

@implementation NSMutableDictionary (IntKeyDictionary)
- (void) setObject:(id)obj forId:(int)id {
  [self setObject:obj forKey:[NSNumber numberWithInt:id]];
}

- (void) removeObjectForId:(int)id {
  [self removeObjectForKey:[NSNumber numberWithInt:id]];
}

- (id) objectForId:(int)id {
  return [self objectForKey:[NSNSumber numberWithInt:id]];
}
@end
Ed Marty