Słownik z klawiszami enum?
Muszę utworzyć słownik / hashmap gdzie
- Klucze to liczby
- wartości są podklasą
NSObject
NSDictionary
tutaj nie będzie działać (liczby nie są zgodne z NSCopying
).
Mógłbym użyć CFDictionaryRef
tutaj, ale chciałbym wiedzieć, czy jest jakiś inny sposób, aby to osiągnąć.
5 answers
Ponieważ liczby są liczbami całkowitymi, można je zawinąć w NSNumber. Kiedy dodajesz / wycofujesz coś do / z mapy, przekazujesz enum do konstruktora NSNumber...
Zakładając, że masz enum jak...
enum ETest {
FOO, BAR
};
Możesz go użyć w takim NSDictionary...
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
[dict setObject: @"Foo!" forKey:[NSNumber numberWithInt: FOO]];
NSLog(@"getting value for FOO -> %@",
[dict objectForKey: [NSNumber numberWithInt: FOO]]);
[dict release];
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-07-27 09:33:29
Z sugestią Voidpointera, może być lepiej użyć NSValue
w tych czasach, kiedy Enemy okazują się nie być liczbami całkowitymi (np. gdy -fshort-enums
jest w grze, co nigdy nie powinno być, ponieważ prawdopodobnie złamałbyś kompatybilność z Fundacją).
NSValue *value = [NSValue value: &myEnum withObjCType: @encode(enum ETest)];
To nie będzie wiele dodawać, ale daje ogólną technikę "chcę użyć
Zauważ, że w nowoczesnych kompilatorach możesz powiedzieć enums, aby używały stałego bazowego typu . To oznacza to, że możesz kontrolować, jakie miejsce pamięci jest używane dla enum, ale ponieważ powyższe rozwiązanie jest ogólne, nadal ma zastosowanie, nawet jeśli wiesz o tym.
Kontynuując sugestię Grahama Lee...
Możesz użyć kategorii objective-c , aby dodać metodę do NSMutableDictionary, która pozwala dodać wartość za pomocą klucza typu non NSObject. Dzięki temu kod jest wolny od składni zawijania/rozpakowywania.
Ponownie, zakładając
enum ETest { FOO, BAR };
Najpierw dodajemy konstruktor przekonujący do nsvalue:
@interface NSValue (valueWithETest)
+(NSValue*) valueWithETest:(enum ETest)etest;
@end
@implementation NSValue (valueWithETest)
+(NSValue*) valueWithETest:(enum ETest)etest
{
return [NSValue value: &etest withObjCType: @encode(enum ETest)];
}
@end
Następnie dodamy wsparcie' enum ETest ' do NSMutableDictionary
@interface NSMutableDictionary (objectForETest)
-(void) setObject:(id)anObject forETest:(enum ETest)key;
-(id) objectForETest:(enum ETest)key;
@end
@implementation NSMutableDictionary (objectForETest)
-(void) setObject:(id)anObject forETest:(enum ETest)key
{
[self setObject: anObject forKey:[NSValue valueWithETest:key]];
}
-(id) objectForETest:(enum ETest)key
{
return [self objectForKey:[NSValue valueWithETest:key]];
}
@end
Oryginalny przykład można więc przekształcić do
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
[dict setObject: @"Bar!" forETest:BAR];
NSLog(@"getting value Bar -> %@", [dict objectForETest: BAR]);
[dict release];
W zależności od tego, jak bardzo używasz enum, aby uzyskać dostęp do słownika, może to znacznie ułatwić czytelność kodu.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-07-27 13:20:07
Enums don ' t conform to NSCopying
Jest to niedopowiedzenie; liczby nie "odpowiadają" do niczego, ponieważ nie są obiektami; są prymitywnymi wartościami C, które są wymienne z liczbami całkowitymi. To jest prawdziwy powód, dla którego nie mogą być używane jako klucze. Klucze i wartości NSDictionary
muszą być obiektami. Ale ponieważ liczby są liczbami całkowitymi, możesz je po prostu zawinąć w NSNumber
obiekty. Jest to prawdopodobnie najprostsza opcja.
Inna opcja, jeśli liczby są ciągłe od 0 do pewnej liczby (np. nie ustawiłeś żadnych wartości ręcznie), jest to, że możesz użyć NSArray
, gdzie indeks reprezentuje wartość klucza enum. (Wszelkie "brakujące" wpisy musiałyby być wypełnione NSNull
.)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-07-27 08:53:50
Lubię podejście kategorii również i prawdopodobnie zaimplementuje to również w moim przypadku. Z nowymi literałami / wyrażeniami bokserskimi, jak to się nazywa, czy używanie @(FOO) zajmie się boksem dla Ciebie?
Myślę, że tak, a jeśli tak, działa bardzo przejrzyście, wyraźnie boksując enum, gdy używasz go jako klucza.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-11-09 11:36:07