2009-06-18 24 views
17

Le enumerazioni non sono consentite come chiavi per NSMutableDictionary?tipo typedef enum come chiave per NSDictionary?

Quando provo ad aggiungere al dizionario tramite:

[self.allControllers setObject:aController forKey:myKeyType]; 

ottengo l'errore:

error: incompatible type for argument 2 of 'setObject:forKey:'

In genere, io uso NSString come il mio nome della chiave che non richiede un cast di 'id' ma per far sparire l'errore, l'ho fatto. Il casting è il comportamento corretto qui o sono enumerie come chiavi una cattiva idea?

mio enum è definito come:

typedef enum tagMyKeyType 
{ 
    firstItemType = 1, 
    secondItemType = 2 
} MyKeyType; 

E il dizionario è definito e adeguatamente ripartito come ad esempio:

NSMutableDictionary *allControllers; 

allControllers = [[NSMutableDictionary alloc] init]; 
+0

perché non usi solo un array? – user102008

risposta

21

Tuttavia è possibile memorizzare l'enumerazione in un NSNumber. (Non sono solo enanti?)

[allControllers setObject:aController forKey:[NSNumber numberWithInt: firstItemType]]; 

In Cocoa, vengono spesso utilizzate le NSString cost. Nella .h si dovrebbe dichiarare qualcosa di simile:

NSString * const kMyTagFirstItemType; 
NSString * const kMyTagSecondtItemType; 

E nel file .m si sarebbe messo

NSString * const kMyTagFirstItemType = @"kMyTagFirstItemType"; 
NSString * const kMyTagSecondtItemType = @"kMyTagSecondtItemType"; 

quindi è possibile utilizzare come una chiave in un dizionario.

[allControllers setObject:aController forKey:kMyTagFirstItemType]; 
+2

Penso che vogliate usare la parola chiave 'extern' nel file .h qui, corretta? –

+0

Puoi anche usare 'FOUNDATION_EXPORT' come la parola chiave che credo sia typedef a' extern'. –

3

No, non puoi. Guarda la firma del metodo: id specifica un oggetto. Un tipo enum è uno scalare. Non puoi lanciare da uno all'altro e aspettarti che funzioni correttamente. Devi usare un oggetto.

+5

Questo è vero. Tuttavia, è possibile racchiudere il valore enum in un NSNumber e utilizzarlo come chiave. – LBushkin

4

Questa è una vecchia domanda, ma può essere aggiornata per utilizzare una sintassi più moderna. In primo luogo, come di iOS 6, Apple consiglia di enumerazioni essere definiti come:

typedef NS_ENUM(NSInteger, MyEnum) { 
    MyEnumValue1 = -1, // default is 0 
    MyEnumValue2, // = 0 Because the last value is -1, this auto-increments to 0 
    MyEnumValue3 // which means, this is 1 
}; 

Poi, dal momento che abbiamo l'enum rappresentato come NSInteger s internamente, possiamo box in NSNumber s per memorizzare come la chiave per un dizionario .

NSMutableDictionary *dictionary = [NSMutableDictionary dictionary]; 

// set the value 
dictionary[@(MyEnumValue1)] = @"test"; 

// retrieve the value 
NSString *value = dictionary[@(MyEnumValue1)]; 

EDIT: Come creare un dizionario Singleton per questo scopo

Attraverso questo metodo, è possibile creare un dizionario Singleton per assistere con questo. Nella parte superiore di qualsiasi file che si dispone, è possibile utilizzare:

static NSDictionary *enumTranslations; 

Poi, nel tuo init o viewDidLoad (se si sta facendo questo in un controller di interfaccia utente), si può fare questo:

static dispatch_once_t onceToken; 
// this, in combination with the token above, 
// will ensure that the block is only invoked once 
dispatch_async(&onceToken, ^{ 
    enumTranslations = @{ 
     @(MyEnumValue1): @"test1", 
     @(MyEnumValue2): @"test2" 
     // and so on 
    }; 
}); 




// alternatively, you can do this as well 
static dispatch_once_t onceToken; 
// this, in combination with the token above, 
// will ensure that the block is only invoked once 
dispatch_async(&onceToken, ^{ 
    NSMutableDictionary *mutableDict = [NSMutableDictionary dictionary]; 
    mutableDict[@(MyEnumValue1)] = @"test1"; 
    mutableDict[@(MyEnumValue2)] = @"test2"; 
    // and so on 

    enumTranslations = mutableDict; 
}); 

Se si desidera che questo dizionario sia visibile esternamente, spostare la dichiarazione statica sul file di intestazione (.h).