Тип перечисления typedef как ключ к NSDictionary? - PullRequest
17 голосов
/ 18 июня 2009

Разрешены ли перечисления в качестве ключей для NSMutableDictionary?

Когда я пытаюсь добавить в словарь через:

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

Я получаю ошибку:

ошибка: несовместимый тип для аргумента 2 из 'setObject: forKey:'

Как правило, я использую NSString в качестве имени ключа, который не требует приведения к 'id', но чтобы устранить ошибку, мне пришлось это сделать. Является ли приведение правильного поведения здесь или перечисления как ключи - плохая идея?

Мое перечисление определяется как:

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

И словарь определен и правильно выделен следующим образом:

NSMutableDictionary *allControllers;

allControllers = [[NSMutableDictionary alloc] init];

Ответы [ 3 ]

21 голосов
/ 18 июня 2009

Вы можете сохранить перечисление в NSNumber. (Разве перечисления не просто целые числа?)

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

В Какао часто используются const NSStrings. В .h вы бы объявили что-то вроде:

NSString * const kMyTagFirstItemType;
NSString * const kMyTagSecondtItemType;

А в файле .m вы бы поместили

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

Тогда вы можете использовать его как ключ в словаре.

[allControllers setObject:aController forKey:kMyTagFirstItemType];
4 голосов
/ 29 мая 2015

Это старый вопрос, но его можно обновить, чтобы использовать более современный синтаксис. Во-первых, начиная с iOS 6, Apple рекомендует определять перечисления как:

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
};

Тогда, поскольку у нас есть перечисление, представленное как NSInteger s внутри, мы можем поместить их в NSNumber s для хранения в качестве ключа для словаря.

NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];

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

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

РЕДАКТИРОВАТЬ: Как создать одноэлементный словарь для этой цели

С помощью этого метода вы можете создать одноэлементный словарь, чтобы помочь с этим. Вверху любого файла вы можете использовать:

static NSDictionary *enumTranslations;

Затем в вашем init или viewDidLoad (если вы делаете это в контроллере пользовательского интерфейса), вы можете сделать это:

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;
});

Если вы хотите, чтобы этот словарь был видимым снаружи, переместите статическую декларацию в файл заголовка (.h).

3 голосов
/ 18 июня 2009

Нет, вы не можете. Посмотрите на сигнатуру метода: id указывает объект. Тип enum - это скаляр. Вы не можете кастовать от одного к другому и ожидать, что это будет работать правильно Вы должны использовать объект.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...