Подтвердить что ты не робот

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];
4b9b3361

Ответ 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).