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?
source to share
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 methodhash
for good measure, but probably not necessary.
source to share
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.)
source to share