Tuesday 22 April 2014

Constants in Objective C

When you’re building an app you usually need some values to remain the same for the whole runtime of the app. Instead of using those values everywhere inside your app it is better to define a constant and use the constant instead. It will make your life easier when you want to change the value everywhere in the code and if you give it a good name it will make your code more readable. In this post we’re going to talk about how to define these constants and where to define them so that we end up with a nice design.


In Objective C there are two ways you can make a value remain the same: preprocessing macros and using const storage specifier.


Preprocessing Macros

If you do something like this:


#define MAX_NUMBER_OF_ROWS 10



The value of MAX_NUMBER_OF_ROWS will always be 10 so this sounds like our definition of a constant. This is not an actual constant. It’s called a preprocessing macro because before compile time all the occurrences of MAX_NUMBER_OF_ROWS will be replaced by the actual value, 10 in our case. You’ve probably noticed that we didn’t specify a type for MAX_NUMBER_OF_ROWS. However, because the value gets replaced before compile time, the compiler will complain if you try to assign an int to an NSString for example. You will also get an error if you try to assign a value to MAX_NUMBER_OF_ROWS. So although this is not a constant it does make sure the value is the same and that you have a nice significant name for that value.


Using const

More and more people seem to like this approach better. Instead of using #define you can use const like this:

const int MAX_NUMBER_OF_ROWS = 10;


This actually allocates space for an int. The compiler will flag an error when you try to modify it.
You might be wondering which one to use. Usually you can use any of them. My personal preference is to use const. Together with extern or static you can fine tune your classes and have a clean design.




Understanding extern and static


So how exactly can you use extern and static with constants? As with variables you want the scope of your constant to be as limited as needed. You don’t want to have something public if you’re only using it in your class.
This is where static comes in. If you know that the constant you’re defining is only used in that class then you can define the constant in the .m file before the implementation of the class. Using static means that the constant will only be available in that file.


static NSString * const MY_ID = @"2A3D";


Static can be used with both variables and constants. With variables you can use it in a very nice way to persist a value across methods. If for example you do this:


- (void)oneMethod 
{

    static int x = 0;

    NSLog(@"%d \n", x++);       
}

The output will be:

0
1
2


So the variable is persisted across multiple method calls.
Going back to our constants, if you do want to have a constant global then you should use extern. In the .h file you should define the constant like this:

extern NSString * const MY_ID;





And in the .m file you would actually give it a value:


NSString * const MY_ID = @"2A3D";




This way your API interface will be nice and pretty, you’re not exposing the internals of your class to the world. If you have constants that are used in lots of classes all over the app then it makes sense to have a separate .h and .m file just for defining these constants. This way whenever you need to change the value of one of your constants you know where to look.
Just like variables constants can be defined inside methods or blocks. That means they can be used only in the scope that they have been defined for. Using extern on a const defined in a method doesn’t work, so make sure you define them in the right place when using extern.




No comments:

Post a Comment