Лучший способ перечислить NSString - программирование

Лучший способ перечислить NSString

Im копание путей для перечисления объекта objc, такого как NSString, я помню там новую функцию в версии Xcode4 +, которая предлагает новый способ перечисления, но не ясно. Кто-нибудь знает это?

4b9b3361

Ответ 1

Хорошо, я ответил себе. Думаю, я ошибаюсь.

Это новая функция, о которой я упоминал выше:

typedef enum Language : NSUInteger{
     ObjectiveC,
     Java, 
     Ruby, 
     Python, 
    Erlang 
}Language;

Это просто новый синтаксис перечисления в Xcode 4.4, но я так глупо думать, что мы можем обменять "NSUInteger" на "NSString".

Итак, вот как я нашел, что работает:

http://longweekendmobile.com/2010/12/01/not-so-nasty-enums-in-objective-c/

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

FYI. Оригинальный автор второго примера кода создал категорию для обработки перечислений. Просто для добавления в ваше собственное определение класса NSArray.

@interface NSArray (EnumExtensions)

- (NSString*) stringWithEnum: (NSUInteger) enumVal;
- (NSUInteger) enumFromString: (NSString*) strVal default: (NSUInteger) def;
- (NSUInteger) enumFromString: (NSString*) strVal;

@end

@implementation NSArray (EnumExtensions)

- (NSString*) stringWithEnum: (NSUInteger) enumVal
{
    return [self objectAtIndex:enumVal];
}

- (NSUInteger) enumFromString: (NSString*) strVal default: (NSUInteger) def
{
    NSUInteger n = [self indexOfObject:strVal];
    if(n == NSNotFound) n = def;
    return n;
}

- (NSUInteger) enumFromString: (NSString*) strVal
{
    return [self enumFromString:strVal default:0];
}

@end

Ответ 2

Альтернативный способ использования struct:

extern const struct AMPlayerStateReadable
{
    __unsafe_unretained NSString *ready;
    __unsafe_unretained NSString *completed;
    __unsafe_unretained NSString *playing;
    __unsafe_unretained NSString *paused;
    __unsafe_unretained NSString *broken;
} AMPlayerState;

const struct AMPlayerStateReadable AMPlayerState =
{
    .ready = @"READY",
    .completed = @"COMPLETE",
    .playing = @"PLAYING",
    .paused = @"PAUSED",
    .broken = @"BROKEN"
};

Тогда вы можете использовать так:

NSString *status = AMPlayerState.ready;

Простой в использовании, читаемый. Было бы неплохо, если бы кто-то обновил/отредактировал ответ с преимуществами/недостатками подхода выше.

Ответ 3

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

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]

Ответ 4

Обновление в 2017 году

Недавние голосовые комментарии привлекли мое внимание, и я хотел бы добавить, что enum действительно легко работать с String сейчас:

enum HTTPMethod: String {
    case GET, POST, PUT
}

HTTPMethod.GET.rawValue == "GET" // it true

Оригинальный ответ. К сожалению, я закончил использование:


#define HLCSRestMethodGet       @"GET"
#define HLCSRestMethodPost      @"POST"
#define HLCSRestMethodPut       @"PUT"
#define HLCSRestMethodDelete    @"DELETE"
typedef NSString*               HLCSRestMethod;

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

Update

Быстрая версия кажется более красивой, хотя производительность никогда не будет такой хорошей.

struct LRest {
    enum HTTPMethod: String {
        case Get = "GET"
        case Put = "PUT"
        case Post = "POST"
        case Delete = "DELETE"
    }
    struct method {
        static let get = HTTPMethod.Get
        static let put = HTTPMethod.Put
        static let post = HTTPMethod.Post
        static let delete = HTTPMethod.Delete
    }

}

Ответ 5

Я думаю, что вы ищете встроенную функцию массива. например,

@[@"stringone",@"stringtwo",@"stringthree"];

Если нет, я не уверен, что вы можете перечислять объекты.

вы могли бы иметь статический массив строк и иметь ссылочный объект перечисления в индексе.

Ответ 6

Посмотрите мой ответ в enum Значения для NSString (iOS) - Я считаю, что это может быть более элегантное решение этой проблемы.

Ответ 7

Рекомендуемый способ из яблочных документов:

Вы используете NS_TYPED_ENUM для группировки констант с указанным вами типом необработанного значения. Используйте NS_TYPED_ENUM для наборов констант, которые не могут логически иметь значения, добавленные в расширение Swift, и используйте NS_TYPED_EXTENSIBLE_ENUM для наборов констант, которые могут быть расширены в расширении. Apple, документы

typedef NSString *MyEnum NS_TYPED_ENUM;
extern MyEnum const MyEnumFirstValue;
extern MyEnum const MyEnumSecondValue;
extern MyEnum const MyEnumThirdValue;

в .h файле. Определите свои строки в файле .m

MyEnum const MyEnumFirstValue = @"MyEnumFirstValue"
MyEnum const MyEnumSecondValue = @"MyEnumSecondValue";
MyEnum const MyEnumThirdValue = @"MyEnumThirdValue";

Работает, как и ожидалось, в Objective-C

- (void)methodWithMyEnum:(MyEnum)myEnum { }

и Свифт

func method(_ myEnum: MyEnum) { }