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ąć.

Author: Peres, 2009-07-27

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]; 
 29
Author: VoidPointer,
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ć w klasie kolekcji".

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.

 28
Author: ,
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-07-18 11:03:31

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.

 9
Author: VoidPointer,
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.)

 7
Author: newacct,
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.

 2
Author: FrostyL,
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