views:

240

answers:

4

Hi all. I am a little confused as to when it's best to use:

static NSString *AppQuitGracefullyKey = @"AppQuitGracefully";

instead of

#define AppQuitGracefullyKey    @"AppQuitGracefully"

I've seen questions like this for C or C++, and I think what's different here is that this is specifically for Objective C, utilizing an object, and on a device like the iPhone, there may be stack, code space or memory issues that I don't yet grasp.

One usage would be:

appQuitGracefully =  [[NSUserDefaults standardUserDefaults] integerForKey: AppQuitGracefullyKey];

Or it is just a matter of style?

Thanks.

+1  A: 

If you use a static, the compiler will embed exactly one copy of the string in your binary and just pass pointers to that string around, resulting in more compact binaries. If you use a #define, there will be a separate copy of the string stored in the source on each use. Constant string coalescing will handle many of the dups but you're making the linker work harder for no reason.

cdespinosa
Constant string coalescing is the work of the compiler, not the linker.
KennyTM
A: 

Another reason to use a static string is the compiler / IDE will catch typos for you. In this case

static NSString *AppQuitGracefullyKey = @"AppQuitGracefully";

if you mis-typed your variable name you would be warned.

Also you can call any method on your static string that would normally call with string objects.

darren
The compiler will also warn you if you use the `#define` approach.
KennyTM
A: 

I use static when I need to export NSString symbols from a library or a framework. I use #define when I need a string in many places that I can change easily. Anyway, the compiler and the linker will take care of optimizations.

Laurent Etiemble
+2  A: 

See http://stackoverflow.com/questions/1674032/static-const-vs-define-in-c. The main advantage of static is type safety.

Other than that, the #define approach introduces a flexibility of inline string concatenation which cannot be done with static variables, e.g.

#define ROOT_PATH @"/System/Library/Frameworks"
[[NSBundle bundleWithPath:ROOT_PATH@"/UIKit.framework"] load];

but this is probably not a good style :).

KennyTM
I'm so surprised. I had no idea `@"one string"@" another string"` was valid.
Kenny Winker