Эффективный способ создания упорядоченного набора строковых значений в Objective-C

#objective-c #enums #key-value

#objective-c #перечисления #ключ-значение

Вопрос:

Я хочу создать подобный перечислению набор строк таким образом, который также предоставит мне возможность упорядочивать их по порядковому значению, а НЕ по алфавитному значению. например:

«Чрезвычайно низкий» = 0

«Очень низкий» = 1

«Low» = 2

«Средний = 3

«High» = 4

и так далее.

Я знаю, что, например, в Java и C # типы перечислений могут иметь значение помимо их порядкового значения.

Есть ли какой-либо способ достичь той же цели в Objective-C?

Спасибо!

Ответ №1:

Я не знаю прямого способа сделать это. Однако вы можете определить класс Obj-C следующим образом:

 @interface EnumLike : NSObject
{
    NSString* title;
    NSInteger value;
}

@property (nonatomic, readonly) NSString* title;
@property (nonatomic, readonly) NSInteger value;

// Something like enum
  (id)extremelyLow;
  (id)veryLow;
...
  (id)high;
};
  

За исключением работы с переключателем, это может выполнить работу. Я время от времени использую подобные типы, чтобы объявлять некоторые «перечисления» для пользователя, поскольку список таких экземпляров может быть привязан к NSArrayController и использоваться в пользовательском интерфейсе.

Комментарии:

1. Вау, это великолепно! Это почти именно то, что я ищу. Единственное, чего не хватает, это добавить опцию для создания одного из этих «предопределенных» элементов, указав строку для значения типа «Very Low» и получив обратно соответствующий объект EnumLike. Мне это нужно, потому что я считываю данные из файла, и мне нужно разобрать эти строки во что-то, с чем я могу работать.

Ответ №2:

Просто сохраните строки для ввода-вывода и используйте перечисление для всех ваших вычислений. Например, определите свой enum:

 typedef enum { ExtremelyLow, VeryLow, ... High } Rating;
  

Вы можете использовать это перечисление в switch инструкциях и т.д. Теперь вы можете использовать NSArray или просто C-массив для сопоставления литералов перечисления со строками:

 NSString *RatingToString[] = { @"Extremely Low", @"Very Low", ..., @"High" };

Rating myRating;
NSString *strMyRating = RatingToString[myRating];
  

Переход от строковой версии к перечислению более сложный, вы можете использовать тот же RatingToString массив и выполнить соответствующие сравнения (возможно, без учета регистра, нечеткие и т.д.). Вы также могли бы использовать NSDictionary :

 NSDictionary StringToRating = [NSDictionary dictionaryWithObjectsAndKeys: RatingToString[ExtremelyLow], [NSNumber numberWithInt:ExtremelyLow, ..., nil];
  

Теперь поиск выполнит точное совпадение с вашей строкой и вернет Rating завернутое в NSNumber виде.

Комментарии:

1. Идея словаря выглядит очень хорошо. я могу создать статический массив, подобный этому, и он будет делать именно то, что я хочу — я могу прочитать строку из файла и сразу узнать ее значение, вызвав словарь objectForKey: и передать строку из файла в качестве ключа

2. «NSString *strMyRating = RatingToString[Мой рейтинг];» Вы инициализируете NSString * с помощью char *

Ответ №3:

Вы можете использовать класс, подобный предложенному Gobra, или массив структур c:

 typedef struct {
    int                      type;
    NSString                 *desc;
} NXENumToNSString;



NXENumToNSString kNXGMWidgetTypes[] = {
    {1, @""},
    {2, @"imageGallery"},
    {3, @"dotImageGallery"},
    {4, @"video"},
    {5, @"webView"},
    {6, @"image"}
};

NSInteger  
intToStringForArray(NXENumToNSString *buffer, size_t length, NSString *str) 
{
    int result = NSIntegerMin;
    NXENumToNSString *scan, *stop;  
    scan = buffer;
    stop = scan   length;
    while (scan < stop) {
        if ([scan->desc isEqualToString:str]) {
            result = scan->type;
            break;
        }
        scan  ;
    }
    return resu<
}
  

затем вы можете сделать что-то вроде этого:

  size_t l = sizeof(kNXGMWidgetTypes) / sizeof(NXENumToNSString);
 NSInteger result = intToStringForArray(kNXGMWidgetTypes, l, str);