2009-10-20 5 views
2

J'ai une situation où je veux mapper une paire d'objets à un dictionnaire d'informations. Je voudrais éviter de créer un NSDictionary de NSDictionaries de NSDictionaries puisque c'est simplement confus et difficile à maintenir.Comment dois-je construire un NSDictionary avec plusieurs clés?

Par exemple, si j'ai deux classes, Foo et Bar, je veux {Foo, Bar} -> {NSDictionary}

Y at-il d'autres options que de simplement faire une classe personnalisée (juste à utiliser comme le dictionnaire key) basé sur les deux types en question? Peut-être quelque chose qui ressemble au type de paire de STL que je ne connais pas?

Répondre

5

Comme vous l'avez dit, vous pouvez créer une classe Pair:

//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 

Modifier :

Quelques notes sur la création d'objets qui peuvent être clés:

  1. Ils doivent se conformer à la NSCopying protocole, puisque nous ne voulons pas que la clé change de dessous.
  2. Puisque la paire elle-même est copiée, je m'assure que les objets de la paire sont également copiés. Les touches doivent mettre en œuvre isEqual:. J'applique la méthode hash pour faire bonne mesure, mais ce n'est probablement pas nécessaire.
+0

Dave, 2 questions. 1) Je veux allocWithZone dans copyWithZone, non? 2) L'utilisation de l'ID au lieu de NSObject *? – nall

+3

Si vous implémentez isEqual: vous devez absolument implémenter -hash. L'invariant est que si [a estEqual: b], alors [un hash] doit == [b hash]. – Ken

+0

@nall (désolé, raté votre commentaire) 1: '+ alloc' est implémenté en appelant' + allocWithZone: ', donc cela ne devrait probablement pas faire la différence. 2: Il n'y a pas de réel avantage. Je préfère 'id ' parce que c'est a) moins de type et b) les initialiseurs retournent 'id', pas' NSObject * '(ou une variante similaire). Vrai, vous aurez * rarement * un initialiseur qui ne retourne pas une sous-classe 'NSObject', mais ce n'est pas impossible. 'NSObject' n'est pas la seule classe racine. –

3

Vous pouvez essayer NSMapTable, alors votre clé peut être à peu près n'importe quoi, peut-être un pointeur vers une structure si vous le souhaitez.

(Addendum aux commentaires ci-dessous: NSMapTable était une fois pas sur iOS, mais il est disponible à partir de iOS 6.)

+0

C'est un bon indice, mais NSMapTable n'est pas disponible dans iOS (actuellement 5.0.1). – auco

+0

Cela a du sens, car NSMapTable a été principalement développé en complément de la récupération de place Objective-C (bien qu'il soit très utile dans les environnements non-GC). Il y a toujours CFMutableDictionary si vous voulez quelque chose qui se comporte comme le dictionnaire NS (Mutable) mais qui supporte les types non-object. –

+0

plus d'infos sur NSMapTable: http://stackoverflow.com/questions/6904533/nsmaptable-and-nsmutabledictionary-differences/12186329#12186329 –

0

Est-ce en utilisant quelque chose à l'effet de

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

pas bon pour vous, où key_as_string fait partie de votre classe d'objet? c'est-à-dire faire une clé à partir d'une chaîne.

Questions connexes