Leonardo
Leonardo

Reputation: 9857

About declaring constant in objective-c

if you don't take #define into account, there are two notorious ways for declaring constants in objective-c project:

// Util.h
extern NSString * const MyConstant;

// Util.m
NSString * const MyConstant = @"value";

or the other directly in header file

// Util.h
static NSString *const MyConstant = @"value";

Now, there comes two questions:

1) Both works, the second method is quite convenient, as I have only one place for editing values. However as I saw from Apple .h files, the first method is always preferred, and I wonder if there are any downside, with the static method.

2) Looking at Apple docs, we often encounter very long constant name like: NSTextInputContextKeyboardSelectionDidChangeNotification. In the case you used a long constant name like that, what convention would you generally use to assign a value. If I want to use something descriptive I could use @"nsTextInputContextKeyboardSelectionDidChangeNotification", but sounds little odd.

Upvotes: 2

Views: 321

Answers (2)

Sulthan
Sulthan

Reputation: 130102

I won't explain you all the specifics of the two types of constant declaration - in short:

The first one separates constant declaration from constant definition. Only declaration is included by header files. It also conveniently hides the actual value of the constant.

The second one is more problematic - the header file contains both declaration and definition of the constant. That means that whenewer you include the header, the constant is created again. I don't think this will work correctly when included from multiple files.

The second question - no problem with long constant names. Your example is a bit extreme but there is nothing wrong with it.

EDIT: Adding more information about the static NSString* const in header. Let's have a header A.h:

//A.h
static NSString *const MyConstant = @"value";

and file including it A.m

//A.m
#import "A.h"

printA() {
   NSLog(@"A.h Constant: %@", MyConstant);
}

First note that headers are removed by the preprocessor before compilation. That means that before compilation there won't be any A.h file and A.m will look like this:

//A.m
static NSString *const MyConstant = @"value";

printA() {
   NSLog(@"A.h Constant: %@", MyConstant);
}

Let's create another constant header B.h and implementation file B.m with exactly the same contents:

//B.h
static NSString *const MyConstant = @"value2";
//B.m
#import "B.h"

printB() {
   NSLog(@"B.h Constant: %@", MyConstant);
}

Note that the constant is declared twice, with the same name and different values. This is possible because static makes the constant private for the file that includes it. If you remove the static, you'll get a compilation error because the compiler will find two public global constants with the same name.

In theory it is possible to use static NSString* const in header files and everything will work correctly but as you can see, it doesn't do exactly what you want and can be a source of difficult-to-find bugs. That's why you should use static only from implementation files.

Upvotes: 5

Abizern
Abizern

Reputation: 150605

Just to add - the second way that you have shown doesn't make much sense.

If you are going to declare and define a constant in one place such as this, it's usually done in the .m file and not the .h file.

You do it this way for constants that are only going to be used in the class itself and not exposed.

Upvotes: 0

Related Questions