Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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 i s 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";
like image 294
GuidoMB Avatar asked Dec 29 '09 23:12

GuidoMB


People also ask

What is Objective-C use for?

Objective-C is the primary programming language you use when writing software for OS X and iOS. It's a superset of the C programming language and provides object-oriented capabilities and a dynamic runtime.

Is Objective-C harder than C++?

In my opinion, probably the biggest difference is the syntax. You can achieve essentially the same things in either language, but in my opinion the C++ syntax is simpler while some of Objective-C's features make certain tasks (such as GUI design) easier thanks to dynamic dispatch.

Is Objective-C used anymore?

While Objective-C is still supported by Apple and will likely not be deprecated anytime soon, there will be no updates to the language.

Is Objective-C better than Swift?

Objective-C has a superior runtime compared to Swift. It's probably going to be several years before Swift can catch up. If you're using powerful SDKs, Objective-C is also your best option here as well. I'd still recommend that new developers start off learning Swift.


2 Answers

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.

like image 124
e.James Avatar answered Nov 11 '22 06:11

e.James


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.

like image 42
Chuck Avatar answered Nov 11 '22 04:11

Chuck