How am I supposed to build NSDictionary with multiple keys?

I have a situation where I want to map a couple of objects to a dictionary of information. I would like to avoid creating NSDictionary from NSDictionaries from NSDictionaries as this is just confusing and difficult to maintain.

For example, if I have two classes, Foo and Bar, I want {Foo, Bar} → {NSDictionary}

Are there other options than just creating a custom class (just for use as a dictionary key) based on the two types? Maybe something similar to the STL pair type that I just don't know about?

+2


source to share


3 answers


As you said, you can create a Pair class:

//Pair.h
@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;
@end

//Pair.m
#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];
}

@end

      

Edit:



Some notes on creating objects that can be keys:

  • They must comply with the protocol NSCopying

    , since we do not want the key to change from under us.
  • Since the pair itself is copied, I'm sure the objects in the pair are copied as well.
  • Keys must implement isEqual:

    . I am implementing a method hash

    for good measure, but probably not necessary.
+5


source


You can try NSMapTable , then your key can be pretty much anything, possibly a pointer to a struct if you want.



(Adding to comments below: NSMapTable was not once in iOS, but is available as iOS 6.)

+3


source


Uses something with effect

[NSString stringWithFormat: @ "% @% @", [obj1 key_as_string], [oj2 key_as_string]]

doesn't work for you where key_as_string is part of your object class? those. make a key from a string.

0


source







All Articles