Перечислим значения в NSString (iOS) - PullRequest
63 голосов
/ 13 июня 2011

У меня есть перечисление, содержащее несколько значений:

enum {value1, value2, value3} myValue;

В определенный момент в моем приложении я хочупроверьте, какое значение перечисления сейчас активно.Я использую NSLog, но мне не ясно, как отобразить текущее значение перечисления (value1 / valu2 / valu3 / etc ...) в качестве строки NSSt для NSLog.

Anyone?

Ответы [ 16 ]

84 голосов
/ 11 июля 2013

Мне не нравилось помещать перечисление в кучу, не предоставляя функцию кучи для перевода. Вот что я придумал:

typedef enum {value1, value2, value3} myValue;
#define myValueString(enum) [@[@"value1",@"value2",@"value3"] objectAtIndex:enum]

При этом объявления enum и string хранятся близко друг к другу для простого обновления при необходимости.

Теперь в любом месте кода вы можете использовать перечисление / макрос следующим образом:

myValue aVal = value2;
NSLog(@"The enum value is '%@'.", myValueString(aVal));

outputs: The enum value is 'value2'.

Чтобы гарантировать индексы элементов, вы всегда можете явно объявить начальные (или все) значения перечисления.

enum {value1=0, value2=1, value3=2};
55 голосов
/ 12 июля 2011

Здесь ответили: несколько предложений по реализации

Суть в том, что Objective-C использует обычный старый C enum, который просто прославленнабор целых чисел.

Учитывая enum как это:

typedef enum { a, b, c } FirstThreeAlpha;

Ваш метод будет выглядеть так:

- (NSString*) convertToString:(FirstThreeAlpha) whichAlpha {
    NSString *result = nil;

    switch(whichAlpha) {
        case a:
            result = @"a";
            break;
        case b:
            result = @"b";
            break;
        case c:
            result = @"c";
            break;

        default:
            result = @"unknown";
    }

    return result;
}
34 голосов
/ 21 февраля 2013

Я представлю, как я использую, и это выглядит лучше, чем предыдущий ответ. (Я думаю)

Я хотел бы проиллюстрировать с помощью UIImageOrientation для простоты понимания.

typedef enum {
    UIImageOrientationUp = 0,            // default orientation, set to 0 so that it always starts from 0
    UIImageOrientationDown,          // 180 deg rotation
    UIImageOrientationLeft,          // 90 deg CCW
    UIImageOrientationRight,         // 90 deg CW
    UIImageOrientationUpMirrored,    // as above but image mirrored along other axis. horizontal flip
    UIImageOrientationDownMirrored,  // horizontal flip
    UIImageOrientationLeftMirrored,  // vertical flip
    UIImageOrientationRightMirrored, // vertical flip
} UIImageOrientation;

создать метод, подобный:

NSString *stringWithUIImageOrientation(UIImageOrientation input) {
    NSArray *arr = @[
    @"UIImageOrientationUp",            // default orientation
    @"UIImageOrientationDown",          // 180 deg rotation
    @"UIImageOrientationLeft",          // 90 deg CCW
    @"UIImageOrientationRight",         // 90 deg CW
    @"UIImageOrientationUpMirrored",    // as above but image mirrored along other axis. horizontal flip
    @"UIImageOrientationDownMirrored",  // horizontal flip
    @"UIImageOrientationLeftMirrored",  // vertical flip
    @"UIImageOrientationRightMirrored", // vertical flip
    ];
    return (NSString *)[arr objectAtIndex:input];
}

Все, что вам нужно сделать, это:

  1. назовите вашу функцию.

  2. скопировать содержимое enum и вставить его между NSArray * arr = @ [ и ]; return (NSString *) [arr objectAtIndex: input];

  3. поставить несколько @, "и запятую

  4. PROFIT !!!!

29 голосов
/ 21 февраля 2014

Это будет проверено компилятором, поэтому вы не будете смешивать индексы случайно.

NSDictionary *stateStrings =
 @{
   @(MCSessionStateNotConnected) : @"MCSessionStateNotConnected",
   @(MCSessionStateConnecting) : @"MCSessionStateConnecting",
   @(MCSessionStateConnected) : @"MCSessionStateConnected",
  };
NSString *stateString = [stateStrings objectForKey:@(state)];

var stateStrings: [MCSessionState: String] = [
    MCSessionState.NotConnected : "MCSessionState.NotConnected",
    MCSessionState.Connecting : "MCSessionState.Connecting",
    MCSessionState.Connected : "MCSessionState.Connected"
]
var stateString = stateStrings[MCSessionState.Connected]
13 голосов
/ 26 февраля 2013

Я нашел этот веб-сайт (из которого взят пример, приведенный ниже), который обеспечивает элегантное решение этой проблемы.Оригинальная публикация, однако, взята из этого ответа StackOverflow .

// Place this in your .h file, outside the @interface block
typedef enum {
    JPG,
    PNG,
    GIF,
    PVR
} kImageType;
#define kImageTypeArray @"JPEG", @"PNG", @"GIF", @"PowerVR", nil

...

// Place this in the .m file, inside the @implementation block
// A method to convert an enum to string
-(NSString*) imageTypeEnumToString:(kImageType)enumVal
{
    NSArray *imageTypeArray = [[NSArray alloc] initWithObjects:kImageTypeArray];
    return [imageTypeArray objectAtIndex:enumVal];
}

// A method to retrieve the int value from the NSArray of NSStrings
-(kImageType) imageTypeStringToEnum:(NSString*)strVal
{
    NSArray *imageTypeArray = [[NSArray alloc] initWithObjects:kImageTypeArray];
    NSUInteger n = [imageTypeArray indexOfObject:strVal];
    if(n < 1) n = JPG;
    return (kImageType) n;
}
6 голосов
/ 13 января 2015

Если я могу предложить другое решение, которое имеет дополнительное преимущество проверки типов, предупреждений, если вам не хватает значения enum в вашем преобразовании, читаемости и краткости.

Для вашего данного примера: typedef enum { value1, value2, value3 } myValue; вы можете сделать это:

NSString *NSStringFromMyValue(myValue type) {
    const char* c_str = 0;
#define PROCESS_VAL(p) case(p): c_str = #p; break;
    switch(type) {
            PROCESS_VAL(value1);
            PROCESS_VAL(value2);
            PROCESS_VAL(value3);
    }
#undef PROCESS_VAL

    return [NSString stringWithCString:c_str encoding:NSASCIIStringEncoding];
}

Как примечание. Лучше объявить ваши перечисления так:

typedef NS_ENUM(NSInteger, MyValue) {
    Value1 = 0,
    Value2,
    Value3
}

С этим вы получаете безопасность типов (в данном случае NSInteger), вы устанавливаете ожидаемое смещение перечисления (= 0).

5 голосов
/ 24 ноября 2014

В некоторых случаях, когда вам нужно преобразовать enum -> NSString и NSString -> enum, может быть проще использовать typedef и #define (или const NSStrings) вместо enum:

typedef NSString *        ImageType;
#define ImageTypeJpg      @"JPG"
#define ImageTypePng      @"PNG"
#define ImageTypeGif      @"GIF"

изатем просто работайте с именованными строками, как с любой другой строкой NSString:

@interface MyData : NSObject
@property (copy, nonatomic) ImageType imageType;
@end

@implementation MyData
- (void)doSomething {
    //...
    self.imageType = ImageTypePng;
    //...
    if ([self.imageType isEqualToString:ImageTypeJpg]) {
        //...
    }
}
@end
4 голосов
/ 23 октября 2014

В приведенном ниже решении используется оператор stringize препроцессора, позволяющий получить более элегантное решение. Это позволяет вам определять термины enum только в одном месте для большей устойчивости к опечаткам.

Сначала определите свой enum следующим образом.

#define ENUM_TABLE \
X(ENUM_ONE),    \
X(ENUM_TWO)    \

#define X(a)    a
typedef enum Foo {
    ENUM_TABLE
} MyFooEnum;
#undef X

#define X(a)    @#a
NSString * const enumAsString[] = {
    ENUM_TABLE
};
#undef X

Теперь используйте его следующим образом:

// Usage
MyFooEnum t = ENUM_ONE;
NSLog(@"Enum test - t is: %@", enumAsString[t]);

t = ENUM_TWO;
NSLog(@"Enum test - t is now: %@", enumAsString[t]);

который выводит:

2014-10-22 13:36:21.344 FooProg[367:60b] Enum test - t is: ENUM_ONE
2014-10-22 13:36:21.344 FooProg[367:60b] Enum test - t is now: ENUM_TWO

@ ответ пикселя указал мне правильное направление.

2 голосов
/ 14 сентября 2016

Это старый вопрос, но если у вас есть несмежное перечисление, используйте словарный литерал вместо массива:

typedef enum {
    value1 = 0,
    value2 = 1,
    value3 = 2,

    // beyond value3
    value1000 = 1000,
    value1001
} MyType;

#define NSStringFromMyType( value ) \
( \
    @{ \
        @( value1 )    : @"value1", \
        @( value2 )    : @"value2", \
        @( value3 )    : @"value3", \
        @( value1000 ) : @"value1000", \
        @( value1001 ) : @"value1001", \
    } \
    [ @( value ) ] \
)
2 голосов
/ 20 мая 2016

Ниже приведен пример Enum Struct, дружественного к Objective-C, если вам нужно использовать Swift Code в устаревших проектах, написанных на Objective-C.

Пример:

contentType.filename. toString ()

возвращает имя файла


contentType.filename. rawValue

возвращает значение Int, 1 (начиная со второго элемента в структуре)

@objc enum contentType:Int {

    //date when content was created [RFC2183]
    case creationDate

    //name to be used when creating file    [RFC2183]
    case filename

    //whether or not processing is required [RFC3204]
    case handling

    //date when content was last modified   [RFC2183]
    case modificationDate

    //original field name in form   [RFC7578]
    case name

    //Internet media type (and parameters) of the preview output desired from a processor by the author of the MIME content [RFC-ietf-appsawg-text-markdown-12]
    case previewType

    //date when content was last read   [RFC2183]
    case readDate

    //approximate size of content in octets [RFC2183]
    case size

    //type or use of audio content  [RFC2421]
    case voice

    func toString() -> String {
        switch self {
        case .creationDate:
            return "creation-date"
        case .filename:
            return "filename"
        case .handling:
            return "handling"
        case .modificationDate:
            return "modification-date"
        case .name:
            return "name"
        case .previewType:
            return "preview-type"
        case .readDate:
                return "read-date"
        case .size:
            return "size"
        case .voice:
            return "voice"
        }
    }//eom
}//eo-enum
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...