nall nall - 1 year ago 84
Objective-C Question

How should I construct an NSDictionary with multiple keys?

I have a situation where I want to map a pair of objects to a dictionary of information. I'd like to avoid creating an NSDictionary of NSDictionaries of NSDictionaries since that's simply confusing and difficult to maintain.

For instance if I have two classes, Foo and Bar, I want {Foo, Bar} -> {NSDictionary}

Are there other options than just making a custom class (just to be used as the dictionary key) based on the two types in question? Maybe something akin to STL's pair type that I just don't know about?

Answer Source

Like you said, you can create a Pair class:

@interface Pair : NSOpject <NSCopying> {
  id<NSCopying> left;
  id<NSCopying> right;
@property (nonatomic, readonly) id<NSCopying> left;
@property (nonatomic, readonly) id<NSCopying> right;
+ (id) pairWithLeft:(id<NSCopying>)l right:(id<NSCopying>)r;
- (id) initWithLeft:(id<NSCopying>)l right:(id<NSCopying>)r;

#import "Pair.h"
@implementation Pair
@synthesize left, right;

+ (id) pairWithLeft:(id<NSCopying>)l right:(id<NSCopying>)r {
 return [[[[self class] alloc] initWithLeft:l right:r] autorelease];

- (id) initWithLeft:(id<NSCopying>)l right:(id<NSCopying>)r {
  if (self = [super init]) {
    left = [l copy];
    right = [r copy];
  return self;

- (void) finalize {
  [left release], left = nil;
  [right release], right = nil;
  [super finalize];

- (void) dealloc {
  [left release], left = nil;
  [right release], right = nil;
  [super dealloc];

- (id) copyWithZone:(NSZone *)zone {
  Pair * copy = [[[self class] alloc] initWithLeft:[self left] right:[self right]];
  return copy;

- (BOOL) isEqual:(id)other {
  if ([other isKindOfClass:[Pair class]] == NO) { return NO; }
  return ([[self left] isEqual:[other left]] && [[self right] isEqual:[other right]]);

- (NSUInteger) hash {
  //perhaps not "hashish" enough, but probably good enough
  return [[self left] hash] + [[self right] hash];



Some notes on creating objects that can be keys:

  1. They have to conform to the NSCopying protocol, since we don't want the key to change out from underneath us.
  2. Since the Pair itself is copied, I make sure the objects in the pair are also copied.
  3. Keys have to implement isEqual:. I implement the hash method for good measure, but it's probably not necessary.
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download