Take the 2-minute tour ×

So I have an issue with using a constant variable in the following switch statement in Objective-C.

I have Constants.h with the following:

// Constants.h    
extern NSInteger const TXT_NAME;

And Constants.m as:

// Constants.m
#import "Constants.h"

NSInteger const TXT_NAME        = 1;

Then in TabBasic.m I am trying to use this constant in a switch-case statement:

// TabBasic.m

#import "TabBasic.h"
#import "Constants.h"

... code ...

- (IBAction)saveValue:(id)sender {
    if ([sender isKindOfClass: [UITextField class]]) {
        UITextField *txtField = (UITextField *) sender;

        switch (txtField.tag) {
            case TXT_NAME:
                NSLog(@"Set property name to: %@", txtField.text); 

But unfortunately it is giving me the following two errors on the "case TXT_NAME:" line:

  • Expression is not an integer constant expression
  • Case label does not reduce to an integer constant

Does anyone know what I'm doing wrong? The "tag" variable of a UITextField returns an NSInteger, so I don't see the issue...

Thanks for your help!

share|improve this question

2 Answers 2

up vote 10 down vote accepted

Quick solution, you should place NSInteger const TXT_NAME = 1; in Constants.h, and don't need anything in Constants.m.

Reason: If you set the value of the constant in the .m, it is not visible by other translation units that only include the .h file. The value of the constant must be known at compile time to be able to be used in a case within a switch.


The above works when compiling in Objective-C++. You need to have your files end in .mm instead of .m for them to be compiled in Objective-C++ instead of Objective-C.

In order to work in Objective-C, you should define your constant either like this:

#define TXT_NAME 1

Or even better, like this:

enum {TXT_NAME = 1};

share|improve this answer
This solution will lead to linker errors if constants.h will be imported in several implementation files –  Vladimir Jul 5 '11 at 15:41
@Vladimir, no it will not lead to linker errors, because constants are statically linked by default. –  Thomas Jul 5 '11 at 15:43
@Vladimir, this is in fact only true when compiling in C++. Sorry. –  Thomas Jul 5 '11 at 15:59
@Jules Because the == test in your if statement does not require the constant to be known at compile time. The case: requires a compile time constant value. –  Thomas Jul 5 '11 at 17:23
Using #define for constants is a terrible idea. The point of a constant is to treat text like a symbol, not like characters. –  Samuel Goodwin Dec 12 '12 at 1:30

I would normally follow what Apple seem to do and define a typedef enum in the .h file like this.

typedef NS_ENUM(NSInteger, PSOption) {

You can then use it in your case statement and even pass it into functions as well as a type e.g.

- (void)myMethod:(PSOption)option;

A further advantage of doing this over a #define is code completion and compiler checking

share|improve this answer

Your Answer


