简体   繁体   中英

Objective-C #define directive demonized for String constants

I've reading in several post and in Apple's code guidelines that in Objective-C String constants should be defined as extern NSString *const MY_CONSTANT; and that the #define directive should be avoided. Why is that? I know that #define is run at precompile time but all string will share the same memory address. The only advantage I read was that if the constant must be updated or changed you don't have to recompile your entire project. So that is the reason why #define should be avoided?

Thanks

UPDATE: In this case is good to use a #define or there is a better approach?

/* Constants Definition */
#define SERVER_URL @"http://subdomain.domain.edu.ar/Folder/"
NSString *const ServerURL = SERVER_URL;
NSString *const LoginURL = SERVER_URL@"welcome.asp";
NSString *const CommandURL = SERVER_URL@"com.asp";

A practical reason to use the constant as opposed to the definition is that you can do direct comparisons (using ==) instead of using isEqual: . Consider:

NSString * const kSomeStringConstant = @"LongStringConstantIsLong";
...
[someArray addObject:kSomeStringConstant];
if ([someArray lastObject] == kSomeStringConstant)
{
   ...
}

This would work, since the == comparison would be comparing identical const pointers to a single NSString object. Using #define , however:

#define STRING_CONSTANT @"MacrosCanBeEvil";
...
[SomeArray addObject:STRING_CONSTANT]; // a new const `NSString` is created
if ([someArray lastObject] == STRING_CONSTANT) // and another one, here.
{
    ...
}

This would not work out, since the two strings would have unique pointers. To compare them effectively, you would have to do a character-by-character comparison using isEqual:

if ([[someArray lastObject] isEqual:STRING_CONSTANT])
{
    ...
}

This can be far more costly in terms of execution time than the simple == comparison.

Another motivation could be the size of the executable itself. The #defined constant would actually appear, in place, wherever it was used in the code. This could mean that the string appears many times in your executable. In contrast, the constant should (with modern compilers) be defined only once, and all further usages would make reference to the pointer to that one definition.

Now, before anyone yells at me for premature optimization, consider that the two approaches are almost identical in terms of implementation, but the const pointer method is far superior in terms of code size and execution time.

It's not necessarily guaranteed that there will only be one NXConstantString object for a given string literal in an entire application. It seems pretty likely that different compilation units might have different objects for the same constant string. For example, if somebody writes a plugin, one constant string will be generated for occurrences of that NSString literal in the plugin and one will be generated for occurrences in the host application, and these will not be pointer-equal.

我听过的最好的论点是const字符串出现在调试器中,而宏则没有出现。

static NSString * const SERVER_URL = @"http://subdomain.domain.edu.ar/Folder/";

As far as I know, #define only lets you define C-style string constants. To create a constant NSString object, you have to declare it in the header, and then give it a value in one of your .m files.

Header file:

extern NSString *MyConstantString;

Main file:

NSString *MyConstantString = @"String value";

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM