12

I have several obj-c classes, each of which require a number of constants that are used in switch statements.

I had tried defining these numerical constants in the .m file using the #define preprocessor instruction. All these constants begin with 'kCell'. This seems to work well but Xcode's code sense is presenting me with every 'kCell' prefixed constant no matter where I am in the project. Do #define constants have global scope? If so, what is the best way to define purely local class constants that won't class with similarly named constants in other classes?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Garry Pettet
  • 8,096
  • 22
  • 65
  • 103

4 Answers4

34

Have your own constant file like MyConstants.

In MyConstants.h declare all your constants:

static const int kRedisplayTileCount = 5 ;
extern  NSString* const kCellTitleKey;

and in MyConstants.m define them

NSString* const kCellTitleKey = @"CellTitle";

By keeping constants in separate file, it will be easy for you to trace them and change their value.

This is the best way to define purely constants. And this will avoid duplicate keys also.

Only you need to do is import this class in you other classes:

#import "MyConstants.h"

and use these keys straight away:

obj = [[NSUserDefaults standardUserDefaults] integerForKey: kCellTitleKey];
Eric G
  • 1,429
  • 18
  • 26
Manjunath
  • 4,545
  • 2
  • 26
  • 31
  • 4
    Consistent misspelling, I like that (MyConstatnts). – pauloya Jan 20 '12 at 14:20
  • 4
    You could also put the #import "MyConstants.h" in your Prefix.pch file so it is accessible from all .m files in your project. – Eric G Apr 19 '12 at 21:57
  • But these are not class constants. What if I have two files ClassA.h and ClassB.h and I have a constant `SomeErrorCode =1` in ClassA.h and `SomeErrorCode = 2` in ClassB.h? How do I ensure that in the calling code I can check for ClassA.SomeErrorCode and ClassB.SomeErrorCode and still get two different values, as they are defined in both .h files? – JustAMartin Jan 23 '17 at 16:07
8

I generally find that enums are best used for switches:

typedef enum {
  kCellConstantOne = 1,
  kCellConstantTwo = 2, //...
} kCellConstants;

/* later */
- (void)foo:(kCellConstant)constant {
  switch (constant) {
    case kCellConstantOne:
      //do something
      break;
    case kCellConstantTwo:
      //do something else
      break;
  }
}

Unfortunately xCode doesn't restrict it's code sense (code completion, auto-complete) to any specific file. It tries to figure out which constants are accessible from which areas of your code but I've noticed it's not 100% accurate.

I would suggest not starting them all with the same prefix. For example, if you have two different types of table cells, kCustomCell and kOtherCell might be better ways to name you constants.

ImHuntingWabbits
  • 3,827
  • 20
  • 27
5

The #define constants only exist in the .m file.

If the constants are integers you could also define them in an enum:

enum {
  kCellSomething = 123,
  kCellAnotherThing = 456,
  ...
};
kennytm
  • 510,854
  • 105
  • 1,084
  • 1,005
1

This seems to work well but Xcode's code sense is presenting me with every 'kCell' prefixed constant no matter where I am in the project. Do #define constants have global scope? If so, what is the best way to define purely local class constants that won't class with similarly named constants in other classes?

Xcode Code Sense and Runtime availability are not identical. Xcode also offers selectorNames and other stuff of items that are not visible at runtime.

Everything defined in a .m file is local at runtime.

Also have a look at this question: Constants in Objective-C

Community
  • 1
  • 1
maxbareis
  • 886
  • 9
  • 17