Getting enum as an NSString

5,934 views
Skip to first unread message

Bradley S. O'Hearne

unread,
Oct 25, 2009, 1:56:42 PM10/25/09
to xcodep...@googlegroups.com
Simple Objective C question:

If I have the following enum:

typedef enum _colors {
RED,
GREEN,
BLUE
} MyColors;

How can I convert an enum value of MyColors type to an NSString, i.e.:

MyColors color = RED;
NSString *colorString = ?;

Thanks,

Brad

Saul Mora

unread,
Oct 25, 2009, 3:17:44 PM10/25/09
to xcodep...@googlegroups.com
Hey Brad,

I did some quick research to confirm my thoughts, but basically, since
enums are *really* ints, there isn't any easy way back to the
enumerated string identifiers. Since this is basically the C part of
Objective C, I don't know how you would do what you are asking without
writing your own custom translation function.

See this Q&A on stackoverflow.com: http://stackoverflow.com/questions/1094984/convert-objective-c-typedef-to-its-string-equivalent

Saul

Jiva DeVoe

unread,
Oct 25, 2009, 3:53:00 PM10/25/09
to xcodep...@googlegroups.com
Note:

Const static NSStrings are guaranteed in ObjC to all point to the same
memory location. Meaning:

NSString *a = @"STRING";
NSString *b = @"STRING";

assert(a == b);

Works. Therefore, you can treat const NSStrings as if they are enums
in most code requiring "unique keyed values" (things you would use
enums in typically).

An area to be cautious of, however, is that an NSString that is not
declared using @"" does NOT follow these rules, even if it's text
matches.

So, for example:

NSString *a = @"STRING";

[[NSUserDefaults standardUserDefaults] setObject:a forKey:@"FOO"];

NSString *b = [[NSUserDefaults standardUserDefaults]
objectForKey:@"FOO"];

assert(a == b); // fails - a != b - though [a isEqualToString:b]
would succeed.

So, point is, as long as you treat the NSString as sort of an opaque
type there are some cases when you can skip the enum declaration
altogether, and use const NSStrings instead.

I haven't actually used C enums in ObjC myself in a long while, mainly
because I got used to the C++ syntax for them, and found C enums to be
so inconvenient and annoying that it's not worth it. The simpler
solution for 99% of cases is either to use an NSString directly, or to
use #define with ints.
--
Jiva DeVoe
http://www.random-ideas.net
What's Goin Down - Network Management Tools for your iPhone.

Brad Miller

unread,
Oct 25, 2009, 4:18:22 PM10/25/09
to xcodep...@googlegroups.com

On Oct 25, 2009, at 10:56 AM, Bradley S. O'Hearne wrote:


You need to write a translation method. Just do a case statement on
the values that returns the string you need.

As Saul mentioned, the enum is always some sort of integer. The
compiler infers the type (unsigned, signed, long long) for you. Due
to this, I'd recommend being explicit about your definitions. It's
not really much more work to do and can save you a debugging headache
for a couple edge cases that can crop up when moving from 32-bit to 64-
bit. We're not their yet, but it's not hard to imagine a 64-bit chip
in the iphone in a few years.

type enum {
RED = 0,
GREEN = 1,
BLUE = 2
}
typedef NSUInteger MyColors

I also recommend setting the value over letting the compiler set them
for you. It's a bit safer and more portable. It probably won't
happen, but the compiler could always decide to change the way it
assigns values, say starting at 1 instead of 0. If you're storing
values in preferences or something, they'll then be off if a change
ever did happen. You might also end up working on some platform that
has an oddball compiler that starts at max int and works backwards or
something. If cross platform documents get created, you're going to
have issues. So it's probably not a huge problem, but I feel it's
better to be explicit and safe where ever I can.


Brad Miller
br...@cynicalpeak.com
http://cynicalpeak.com/

Bradley S. O'Hearne

unread,
Oct 25, 2009, 4:55:41 PM10/25/09
to xcodep...@googlegroups.com
Jiva / Saul / Brad,

Thanks for the responses -- all make sense. Jiva, one note: the only
problem with the below is that it doesn't provide enforcement of pre-
defined values -- i.e. the user could throw *any* string at your
functions. Given the responses, here is what I would think might make
the best approach, without having to write any explicit translation
code:

typedef enum _colors {
RED = 0,
GREEN = 1,
BLUE = 2
} MyColors;

NSArray *myColorStrings = [NSArray arrayWithObjects: @"RED", @"GREEN",
@"BLUE", nil];
...
and the associated usage would be:

MyColors color = RED;
NSString *colorString = [myColorStrings objectAtIndex:color];
...

and going back the other way:

color = [myColorStrings indexOfObject:colorString];

I'm guessing at the last one, but it sounds like based upon your
feedback that's probably the best way to handle enums > string
conversion.

Brad
Reply all
Reply to author
Forward
0 new messages