One of the most commonly used features in Java is the ability to avoid string “magic constants” by putting those strings into static variables. These values are then readily accessible inside of the class, not necessarily visible outside of it, and are easy to modify on the fly if and when such is called for. They also allow me to create the string once, saving both memory and time.
When I started trying to build my iPhone application, I ran into the immediate problem: how can I abstract out my strings?
Private Static Strings
We can do the same thing in Objective-C that we can do in Java, but it is a little counter intuitive if you don’t know C.
In the class file, before the implementation, declare the constants as follows:
static NSString *const kConstant = @"myconstant";
There are several components here:
- static – Means that the variable doesn’t have to be declared in the header. Since it is “private,” this makes sense.
- NSString – The type of the object is NSString, though we could use some other basic type in the same way.
- *const – This is a constant pointer. The pointer itself is constant, though in theory the actual value underlying the pointer could change at a later date. If we were to use a pointer to a constant (e.g., const NSString *) the memory contents could not change, but the pointer could be moved around. You can read more about this at cppkid.
Public Static Strings
For public variables, we’ll use the extern keyword.
For this in the header file declare:
extern NSString *const kClick;
…and then in the implementation file:
NSString *const kClick = @"CLICK"
Again we see the use of the “constant pointer” discussed above, except here anyone can access the value by importing the header file.
What about #define?
Macros solve one of the problems with using string magic constants: they provide the level of abstraction so when the macro is modified, it will propagate. Unfortunately if the string is not retained and there is a release pool involved, the string will probably be disposed of and have to be recreated.
I tend to consider it a good practice to avoid preprocessor macros where possible. They have their uses, but can lead to some unpredictable–and compiler dependent–results. This is especially once we get out of the realm of using strings.
So given that there are a few technical reasons to go with one of the above methods and that #define macros have their own quirks, I consider it a “best practice” to go with either extern or static variables for string constants.