31

In the latest tools, a new kind of enums are now allowed:

typedef enum CarType : NSUInteger {
  FourDoorCarType,
  TwoDoorCarType
} CarType;

My question comes in parts:

  1. Why should I use this instead of the old way?

  2. Why does CarType appear twice? I tried skipping the first CarType and just leaving the first line as "typedef enum : NSUInteger {", and it seems to work fine. What are the drawbacks, if any?

  3. Can some types other than NSUInteger be used?

NoobOverflow
  • 1,208
  • 3
  • 14
  • 19

6 Answers6

37

Because this new way helps you with autocompletion, switch statement, better, respectively more precise warnings, ...

Stick with macro ...

typedef NS_ENUM( NSUInteger, CarType ) {
  FourDoorCarType,
  TwoDoorCarType
};

... read this for example https://stackoverflow.com/a/3190470/581190

NSInteger, ... what types do you want?

Community
  • 1
  • 1
zrzka
  • 20,249
  • 5
  • 47
  • 73
  • *How* does it help with autocompletion, switch statements, or warnings? – Mark Amery Jul 31 '13 at 15:17
  • When you do define enum with this macro, it shows you warnings that you do not handle all possible cases in switch statement for example. Imagine you have switch statement with `case FourDoorCarType:` only. It warns you that you do not handle `TwoDoorCarType`, etc. – zrzka Aug 13 '13 at 07:32
19
  1. This explicitly defines the numeric type that the enum uses. This helps with portability concerns. It also helps if you need control over signed vs. unsigned

  2. Two types are actually defined here. The first is enum CarType and the second is CarType, which is an alias of enum CarType. You can omit the first CarType if you want. This just prevents enum CarType from being a defined type, but CarType is still valid. Another common thing people do is something like

    typedef enum _EnumName {
        values
    } EnumName;
    

    What you decide to do here is something of a matter of personal preference.

  3. Yes. You can use any numeric type, although the enum values must be able to fit in the chosen type.

Lily Ballard
  • 182,031
  • 33
  • 381
  • 347
4

One big advantage is that you can forward-declare enums with this syntax:

enum CarType : NSUInteger;

That helps avoiding including large headers in other headers just because of enum definitions.

Jorge Vasquez
  • 563
  • 1
  • 6
  • 13
3

For point 2: it's the "same old syntax" from C: typedef <something> <alias>. Here, something is enum <enumIdent> { <a, b, c, d, ...> }.

You're allowed to use the same name for enumIdent and alias, simply.

Cyrille
  • 25,014
  • 12
  • 67
  • 90
1

the answers would be here for you.

typedef enum MYCARTYPE { // you could drop the ": NSInteger" part to you could drop the the MYCARTYPE name as well, if you like.
  FourDoorCarType,
  TwoDoorCarType
} CarType;

Why should I use this instead of the old way?

you can use the old way at the current stage.

Why does CarType appear twice? I tried skipping the first CarType and just leaving the first line as typedef enum : NSUInteger {, and it seems to work fine. What are the drawbacks, if any?

because you named the enum as CarType and then you named the new type in typedef definition as CarType as well. you don't need to name the enum because you cannot use its name anywhere. the name of the new type should be enough.

Can some types other than NSUInteger be used?

yep, you can, the types are always NSInteger, you don't need to limit them unsigned integer.

holex
  • 23,961
  • 7
  • 62
  • 76
  • Identifiers that start with two underscores are reserved and should not be used. Similarly, identifiers that start with an underscore followed by an uppercase letter are also reserved. – dreamlax Jul 20 '12 at 12:20
  • you are partly right, this kind of names are **really** reserved: `__MATH__` but for the other IDs, which starts with two underscore, there are no convention, so you can use them like `__MATH`. – holex Jul 20 '12 at 12:48
  • 2
    no, I am completely correct, the C standard §7.1.3 says: *All identifiers that begin with an underscore and either an uppercase letter or another underscore are always reserved for any use.* – dreamlax Jul 20 '12 at 13:26
  • ok, in that case, you should inform the Apple about it because I haven't find any same naming convention in the `Apple's Naming Conventions Guide`, and they are using this way for their macros in their frameworks as well. it seems the Apple does not care of the ISO standards. :) – holex Jul 20 '12 at 13:41
  • 2
    Apple's toolchain *is* the implementation though. An implementation is *allowed* to use reserved identifiers, but your application is *not*. – dreamlax Jul 20 '12 at 13:54
  • okay, I hope you are feeling yourself better now, I've changed the name here... but trust me, if the Apple does not mention **this** conventions in its detailed guide then it means no matter. you should know the Apple is very rigorous in everything. – holex Jul 20 '12 at 14:05
  • The important thing to remember is that Objective-C is based on standardised C, so standard C rules still apply, as well as any additional rules provided by Apple. Clauses in the C standard regarding undefined behaviour, implementation-defined behaviour etc still apply in Objective-C, and this includes using reserved identifiers. – dreamlax Jul 20 '12 at 14:16
  • I know you are right, I agree with you it is important. we are working with the `Objective C` but what is not on the Apple's guide for this language there is not important for working with the `Xcode` and `Objective C` and... honestly? I've been working with `ANSI C`, `C++` or `Objective C` for 20 years, I've made many projects, do want to know how many times heading the variable with double underscore `__` caused problem for me? zero time. theoretically it looks an important standard but in the real development it does not cause any problem. this would be why the Apple does not mention it. – holex Jul 20 '12 at 14:25
1

New NS_ENUM also enables you to forward declare as following:

// Forward declaration for XYZCharacterType in other header say XYZCharacter.h
typedef NS_ENUM(NSUInteger, XYZCharacterType);


// Enum declaration header: "XYZEnumType.h"
#ifndef XYZCharacterType_h
#define XYZCharacterType_h

typedef NS_ENUM(NSUInteger, XYZEnumType) {
    XYZCharacterTypeNotSet,
    XYZCharacterTypeAgent,
    XYZCharacterTypeKiller,
};

#endif /* XYZCharacterType_h */`

Forward-declare enum in Objective-C

lal
  • 7,410
  • 7
  • 34
  • 45