Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Global constants in Objective-C

I've a file called Constants.h:

extern NSString * const BASE_URL;

and Constants.m:

#ifdef DEBUG
    NSString * const BASE_URL = @"http://www.example.org ";
#else
    NSString * const BASE_URL = @"http://localhost";
#endif

First question: How can I switch DEBUG to be True and False?


I've a view controller file MyViewController.m:

#import "MyViewController.h"
#import "Constants.h"

// this doesn't works. see above for the error.
static NSString * const ANOTHER_URL = [NSString stringWithFormat:@"%@%@", BASE_URL, @"/path/"];

@implementation HomeViewController

[...]

The code doesn't work and returns me this error:

error: Semantic Issue: Initializer element is not a compile-time constant

How can I fix this?

I need to combine several global string variabile with other strings for create various urls.


UPDATE 1

Now Constants.m is:

#import "Constants.h"

#ifdef DEBUG
    #define DEF_BASE_URL "http://www.example.org/"
#else
    #define DEF_BASE_URL "http://localhost/"
#endif

NSString * const BASE_URL = (NSString*)CFSTR(DEF_BASE_URL);
NSString * const API_URL = (NSString*)CFSTR(DEF_BASE_URL "api/");
NSString * const API_SETTINGS_URL = (NSString*)CFSTR(API_URL "settings/");

But there is an error on the last line Parse error: expected ')'. Probably I can use CFSTR only with macros. I need to find a way for have all my global variables.

like image 659
Fred Collins Avatar asked Nov 06 '11 23:11

Fred Collins


2 Answers

Solution A:

Personally, I would just use a function for ANOTHER_URL.

Solution B:

If you really want a constant: You should be able to use cstring concatenation rules via #define, then pipe that through CFSTR():

// defs.h
extern NSString * const BASE_URL;
extern NSString * const ANOTHER_URL;

// defs.m

#ifdef DEBUG
#define DEF_BASE_URL "http://www.example.org"
#else
#define DEF_BASE_URL "http://localhost"
#endif

NSString * const BASE_URL = (NSString*)CFSTR(DEF_BASE_URL);
NSString * const ANOTHER_URL = (NSString*)CFSTR(DEF_BASE_URL "/path/");

Solution C:

If you want to create just one via initialization, you can also accomplish a function/method local static in C++/ObjC++ translations (then use C or ObjC visibility, where needed):

NSString * URL() {
  static NSString * const ANOTHER_URL = [NSString stringWithFormat:@"%@%@", BASE_URL, @"/path/"];
  return ANOTHER_URL;
}
like image 85
justin Avatar answered Sep 24 '22 21:09

justin


Firstly, you can tell Xcode to set some preprocessor macros for debug builds. Use the build option 'preprocessor macros'.

For your second question, you can't call an objective-C method to fill a constant, because that stuff isn't available at compile-time. Your best option is to define the global variable, then give it a value in the class 'initialize' method.

static NSString * ANOTHER_URL;

+ initialize {
    ANOTHER_URL = [NSString stringWithFormat:@"%@%@", BASE_URL, @"/path/"];
}

initialize is called before your first instance of the class is created, so it's safe. You'll have to drop the const keyword, but I'm sure you can trust yourself! ;)

like image 27
joerick Avatar answered Sep 24 '22 21:09

joerick