26

So, I've got this definition:

typedef enum {
    red = 1,
    blue = 2,
    white = 3
} car_colors;

Then, I've got a variable of type car_colors: car_colors myCar;

The question is, I receive the color of the car in a NSString. It must be a NSString, I can't change that. How can I convert from NSString to car_colors type?

NSString *value = [[NSString alloc] initWithString:@"1"];
myCar = [value intValue]; // <-- doesn't work

any idea? thanks!

FreeAsInBeer
  • 12,937
  • 5
  • 50
  • 82
Hectoret
  • 3,553
  • 13
  • 49
  • 56
  • What exactly doesn't work? Put a breakpoint in the method where you're converting the string to an integer, you should be able to see exactly what part is going haywire. – Marc Charbonneau May 29 '09 at 14:24

6 Answers6

53

here's an implementation using NSDictionary and the existing enum

in .h file:

typedef NS_ENUM(NSInteger, City) {
    Toronto         = 0,
    Vancouver       = 1
 };

@interface NSString (EnumParser)
- (City)cityEnumFromString;
@end

in .m file:

@implementation NSString (EnumParser)

- (City)cityEnumFromString{
    NSDictionary<NSString*,NSNumber*> *cities = @{
                            @"Toronto": @(Toronto),
                            @"Vancouver": @(Vancouver),
                            };
    return cities[self].integerValue;
}

@end

sample usage:

NSString *myCity = @"Vancouver";
City enumValue = [myCity cityEnumFromString];

NSLog(@"Expect 1, Actual %@", @(enumValue));
ThomasW
  • 16,981
  • 4
  • 79
  • 106
  • This should be the accepted answer. Making your enums Arrays or Dictionaries is not a good way to approach this issue. – datWooWoo Oct 29 '15 at 21:18
  • Note that if it the precise values of the enum aren't important, then you don't need to specify the values. – ThomasW Dec 10 '15 at 01:51
18

Rather than use an array, why not use a dictionary; You have the colour NSString as keys, and you return whatever NSNumber you want. Something like; (Long winded for clarity).

NSDictionary *carColourDictionary = @{@"Red": @1,
                                      @"Blue": @2,
                                      @"White": @3};

// Use the dictionary to get the number
// Assume you have a method that returns the car colour as a string:
// - (NSString *)colourAsString;
int carColour = carColourDictionary[object colourAsString];
Abizern
  • 146,289
  • 39
  • 203
  • 257
  • Enum has a different meaning, we cant replace the enum with NSArray or NSDictionary. When you develop libraries you must use proper datatypes. This is not a optimal solution for it. – Anto Binish Kaspar Nov 02 '11 at 12:51
  • 5
    @AntoBinishKaspar The question wasn't about a library it was about working around a particular problem with a particular constraint. And who says you can't replace an enum with a dictionary? I'm not talking about a drop in replacement, I'm talking about a different way of approaching a solution. – Abizern Jan 05 '12 at 16:05
8

You could also put the values in an array.

NSArray *carColorsArray = @[@"red", @"blue", @"white"];

You can then use indexOfObject to get the index of a particular string.

car_colors carColor = [carColorsArray indexOfObject:@"blue"] + 1;
ThomasW
  • 16,981
  • 4
  • 79
  • 106
Tom Jefferys
  • 13,090
  • 2
  • 35
  • 36
3

There are a lot of great answers to this here: Converting between C enum and XML

They are basically the same as Abizern's, but are a little cleaner and easier to work with if your app does this string-to-enum conversion a lot. There are solutions which keep the string and enum definitions together, and ways to make the conversions each a single, easy-to-read line of code.

Community
  • 1
  • 1
andyvn22
  • 14,696
  • 1
  • 52
  • 74
1
// ...
typedef enum {
    One = 0,
    Two,
    Three
} GFN;
// ...
#define kGFNPrefix @"GFNEnum_"
// ...
+ (NSString *)gfnToStr:(GFN)gfn {
    return [NSString stringWithFormat:@"%@%d", kGFNPrefix, gfn];
}

+ (GFN)gfnFromStr:(NSString *)str {
    NSString *gfnStr = [str stringByReplacingOccurrencesOfString:kGFNPrefix withString:@""];
    return [gfnStr intValue];
}
// ...

My choice =)

uranpro
  • 85
  • 1
  • 7
-6

I found the solution:

if ([car_color isEqualToString:@"1"])
        return red;
if ([tipo_pdi isEqualToString:@"2"])
        return blue;
if ([tipo_pdi isEqualToString:@"3"])
        return white;

But I don't like this 'if' style, what if I had a thousand colors? Isn't there a more automatic solution?

Hectoret
  • 3,553
  • 13
  • 49
  • 56