2

My project contains more that 5000 constants over the classes, and I want to reduce the memory for those constants. Which is the best way to use to define the constants in Objective-C?

#define

or

const

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Damodar
  • 707
  • 2
  • 10
  • 23
  • Just curious, why does this matter so much? Have you looked over the overall memory footprint of your app? That seems like the more prudent thing to do first prior to making all the code changes. – Mobile Ben Oct 04 '16 at 19:05

3 Answers3

3

I think the best method to solve your task is using the #define directive. The define directive doesn't use memory at runtime. This directive is executed by a compiler.

Example:

#define MY_CONSTANT @"Hi"

Using in code:

NSString* string = [MY_CONSTANT stringByAppendingString:@" Mac"];

Here you can read about memory allocation for const variables.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Andrew Romanov
  • 4,774
  • 3
  • 25
  • 40
1

Just expanding one of my comments above. The question is

#define MYSTRING @"This is a string"

versus say

NSString *const myString = @"This is a string";

The actual outcome is tool specific. However, examining a binary generated from Xcode, one will find the following:

As expected, both strings must be encoded in the binary, in this case, they will be the __TEXT __cstring as can be verified by running otool -v -s __TEXT __cstring BINARYNAME

Contents of (__TEXT,__cstring) section
0000000100002f19  This is a string

Keep in mind that this technically consumes memory, as the __TEXT is very much loaded into memory during runtime. The larger question, which is related to what the OP was asking is along the lines of "what additional memory outside of __TEXT is incurred by using const".

Remember that the linker will optimize multiple instances of a string. In other words:

NSString *const string1 = @"I'm a string";
NSString *const string2 = @"I'm a string";

will only result in one instance of that string in __cstring in the final binary.

So the overhead of using NSString * seems to be at least a pointer reference. This will be placed either in the __DATA __data or __DATA __const section depending on how it is defined:

NSString *const myString = @"This is a string";

Which would yield:

0000000100003068 (__DATA,__const) non-external (was a private external) _myString

NSString *myString = @"This is a string";

Which would yield:

0000000100003d60 (__DATA,__data) non-external (was a private external) _myString

Note that NSString *const is the way you should be defining it.

So assuming a 64-bit target, your 5,000 string overhead as a const would at least be 40,000 bytes or ~39K. I say at least in case there is some other hidden thing that is being done. But in general, I would expect the pointer to just point to the string in memory.

For most apps, this is probably not very large in the scope of things. So the question one should be asking is what advantages are there for using const?

And for that aspect, I'll save typing and refer you to the following links. It is preferred to use const as the compiler can type check.

Objective-C : #define vs extern const

#define vs const in Objective-C

Community
  • 1
  • 1
Mobile Ben
  • 7,121
  • 1
  • 27
  • 43
0

It actually depends on the case-by-case situation. For your case, I think #define seems to be a better option.

As far as I know:

For #define → No memory access. As token_string will be substituted for each occurrence of identifier, the executable file size increases (storage of literal).

For const → memory will be hit for every access of the variable, and executable file size increases (storage of the variable and storage of a literal which is pointed or referred by the variable).

For a better understanding, please visit "static const" vs "#define" vs "enum" and static const vs #define

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Khushneet
  • 854
  • 9
  • 10