Typedef enum type как ключ к NSDictionary?
Разрешены ли перечисления в качестве ключей для 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];
Ответы
Ответ 1
Однако вы можете сохранить перечисление в NSNumber. (Не перечислены только ints?)
[allControllers setObject:aController forKey:[NSNumber numberWithInt: firstItemType]];
В Cocoa часто используются константы NSStrings. В .h вы бы объявили что-то вроде:
NSString * const kMyTagFirstItemType;
NSString * const kMyTagSecondtItemType;
И в файле .m вы поместите
NSString * const kMyTagFirstItemType = @"kMyTagFirstItemType";
NSString * const kMyTagSecondtItemType = @"kMyTagSecondtItemType";
Затем вы можете использовать его в качестве ключа в словаре.
[allControllers setObject:aController forKey:kMyTagFirstItemType];
Ответ 2
Нет, вы не можете. Посмотрите на подпись метода: id
указывает объект. Тип перечисления является скаляром. Вы не можете отбрасывать от одного к другому и ожидать, что он будет работать правильно. Вы должны использовать объект.
Ответ 3
Это старый вопрос, но его можно обновить, чтобы использовать более современный синтаксис. Во-первых, с 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
};
Затем, поскольку мы имеем enum, представленный как NSInteger
внутренне, мы можем поместить их в NSNumber
для хранения в качестве ключа для словаря.
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
// set the value
dictionary[@(MyEnumValue1)] = @"test";
// retrieve the value
NSString *value = dictionary[@(MyEnumValue1)];
РЕДАКТИРОВАТЬ: для этого нужно создать синглетный словарь
С помощью этого метода вы можете создать однострочный словарь, чтобы помочь в этом. В верхней части любого файла, который у вас есть, вы можете использовать:
static NSDictionary *enumTranslations;
Затем в вашем init
или viewDidLoad
(если вы делаете это в контроллере UI), вы можете сделать это:
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
).