185

I declared an enum in my implementation file as shown below, and declared a variable of that type in my interface as PlayerState thePlayerState; and used the variable in my methods. But I am getting errors stating that it is undeclared. How do I correctly declare and use a variable of type PlayerState in my methods?:

In the .m file

@implementation View1Controller

    typedef enum playerStateTypes
        {
            PLAYER_OFF,
            PLAYER_PLAYING,
            PLAYER_PAUSED
        } PlayerState;

in the .h file:

@interface View1Controller : UIViewController {

    PlayerState thePlayerState;

in some method in .m file:

-(void)doSomethin{

thePlayerState = PLAYER_OFF;

}
syb0rg
  • 8,057
  • 9
  • 41
  • 81
RexOnRoids
  • 14,002
  • 33
  • 96
  • 136
  • 2
    Now the type of the enum is thePlayerState. What does playerStateTypes become? – user4951 Oct 11 '12 at 10:07
  • 3
    For information about NS_ENUM and its latest modern syntax, see the posting [NS_ENUM & NS_OPTIONS](http://nshipster.com/ns_enum-ns_options/) by Mattt Thompson. – Basil Bourque Oct 22 '13 at 00:06

6 Answers6

213

Apple provides a macro to help provide better code compatibility, including Swift. Using the macro looks like this.

typedef NS_ENUM(NSInteger, PlayerStateType) {
  PlayerStateOff,
  PlayerStatePlaying,
  PlayerStatePaused
};

Documented here

rebelzach
  • 2,670
  • 1
  • 17
  • 14
112

Your typedef needs to be in the header file (or some other file that's #imported into your header), because otherwise the compiler won't know what size to make the PlayerState ivar. Other than that, it looks ok to me.

Dave DeLong
  • 242,470
  • 58
  • 448
  • 498
  • The option to put it in a separate file seemed right in my case. I don't know if this is a good approach, but I needed to use the same enum in two different ViewControllers (self and it's delegate/datasource). Importing the header of the delegate/datasource resulted in an error and seems too much for a simple need. So I created a new .h file with the enum declared and imported it on both viewControllers.h file. Worked like a charm. – Leandro Alves May 08 '12 at 17:12
  • 7
    Should recommend to use the NS_ENUM macro - since this is best practice – khebbie Jul 25 '13 at 11:25
  • 1
    You must declare enums using `NS_ENUM` in Objective-C if you want your enum to be available in Swift code. – smileyborg Jan 10 '15 at 04:08
  • @DaveDeLong, Is this still valid in 2015? I have the `typedef` declared in the `.m` file and it compiles and runs well. – Iulian Onofrei Apr 14 '15 at 13:34
  • @IulianOnofrei it would go in the .h file if you need to use the enum in other files. If you only need it in one file, putting it in the .m file has always been perfectly fine. – Dave DeLong Apr 14 '15 at 13:36
  • @DaveDeLong, Understood. – Iulian Onofrei Apr 14 '15 at 13:38
29

In the .h:

typedef enum {
    PlayerStateOff,
    PlayerStatePlaying,
    PlayerStatePaused
} PlayerState;
Ben Flynn
  • 18,524
  • 20
  • 97
  • 142
  • 1
    You can find an answer like this in other SO questions, but when I was reviewing enums, this question popped up first, so I added the answer here too. – Ben Flynn Apr 03 '12 at 20:04
20

With current projects you may want to use the NS_ENUM() or NS_OPTIONS() macros.

typedef NS_ENUM(NSUInteger, PlayerState) {
        PLAYER_OFF,
        PLAYER_PLAYING,
        PLAYER_PAUSED
    };
sean woodward
  • 1,750
  • 1
  • 24
  • 36
  • 2
    ...and more importantly now, you must declare enums using `NS_ENUM` in Objective-C if you want your enum to be available in Swift code. – smileyborg Jan 10 '15 at 04:08
17

This is how Apple does it for classes like NSString:

In the header file:

enum {
    PlayerStateOff,
    PlayerStatePlaying,
    PlayerStatePaused
};

typedef NSInteger PlayerState;

Refer to Coding Guidelines at http://developer.apple.com/

Santhos Ramalingam
  • 1,188
  • 10
  • 11
  • 3
    This doesn't actually help the OP. While technically correct, it doesn't tell them how to create a reusable enum – RyanR Jun 27 '11 at 16:49
  • 27
    Linking to developer.apple.com is not real helpful. Is there some other place you'd like to cite instead? – Brett Aug 13 '12 at 02:16
  • Copy/paste documentation which has already given, the link which is the main page is really not helping to another people... – Onder OZCAN Apr 28 '15 at 07:07
  • 3
    This is now out of date, see this page https://developer.apple.com/library/ios/releasenotes/ObjectiveC/ModernizationObjC/AdoptingModernObjective-C/AdoptingModernObjective-C.html – Alex Chesters Dec 14 '15 at 14:05
9

I recommend using NS_OPTIONS or NS_ENUM. You can read more about it here: http://nshipster.com/ns_enum-ns_options/

Here's an example from my own code using NS_OPTIONS, I have an utility that sets a sublayer (CALayer) on a UIView's layer to create a border.

The h. file:

typedef NS_OPTIONS(NSUInteger, BSTCMBorder) {
    BSTCMBOrderNoBorder     = 0,
    BSTCMBorderTop          = 1 << 0,
    BSTCMBorderRight        = 1 << 1,
    BSTCMBorderBottom       = 1 << 2,
    BSTCMBOrderLeft         = 1 << 3
};

@interface BSTCMBorderUtility : NSObject

+ (void)setBorderOnView:(UIView *)view
                 border:(BSTCMBorder)border
                  width:(CGFloat)width
                  color:(UIColor *)color;

@end

The .m file:

@implementation BSTCMBorderUtility

+ (void)setBorderOnView:(UIView *)view
                 border:(BSTCMBorder)border
                  width:(CGFloat)width
                  color:(UIColor *)color
{

    // Make a left border on the view
    if (border & BSTCMBOrderLeft) {

    }

    // Make a right border on the view
    if (border & BSTCMBorderRight) {

    }

    // Etc

}

@end