Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

#define or const string*

I know this question has been asked several times, but mine is slightly different. Before closing this as duplicate, please read it fully. There are many posts on stack overflow that says, "Personally, I hate MACROS, Don't use that shit". I've read all those and my case is different. I'm trying to define URLs used in a software (iOS app) using #define macros.

I agree that using const strings is a better practice than #define macros. But in an increasingly REST based API world that accepts query parameters as a part of URL, how can you still use const strings to represent a URL that changes?

Instead of http://api.myblog.com/posts?entryid=%@ a API Server that following REST principles would have http://api.blog.com/posts/entries/[entryid]

In the former type, URL is http://api.myblog.com/posts for all entries and they don't change. A const string was possible.

In the latter type, URL changes with every entry and I use a Macro that expands to a full URL like this.

#define GET_ENTRY_URL(__MY_ENTRY_ID__) [NSString stringWithFormat:@"http://api.myblog.com/posts/entries/%@", __MY_ENTRY_ID__];

Are there any design flaws in my method? Would like to know your inputs.

Thanks.

like image 653
Mugunth Avatar asked Nov 07 '11 04:11

Mugunth


2 Answers

Looking from the perspective of the compiler, #define is a preprocessor directive (refer to the definition in c, http://en.wikipedia.org/wiki/C_preprocessor).

In this case, compiler might be doing the whole text replacement before compiling your codes.

e.g.: if you define:

#define GET_ENTRY_URL(__MY_ENTRY_ID__) [NSString stringWithFormat:@"http://api.myblog.com/posts/entries/%@", __MY_ENTRY_ID__];

it could be replacing every occurrences of GET_ENTRY_URL(x) with [NSString ..., x] in your codes. Potentially, instances might be created everywhere we use the macro if the implementation of objective-c is following this.

static const/variable seems to be a better way.

like image 54
alvinsj Avatar answered Nov 14 '22 04:11

alvinsj


What I did in my app was define a const for the base path and a const for each specific path with substitution format codes inside the path when necessary.

NSString const *APIBasePath        = @"http://api.mydomain.com";
NSString const *APIEntryPath       = @"/entries/%d";
NSString const *APIUpdateEntryPath = @"/entries/%d/update";

I then construct the URL at runtime for each API as follows:

- (void)updateEntryNumber:(NSUInteger)entryNumber
{
  NSString *updateEntryPath = [NSString stringWithFormat:APIUpdateEntryPath, entryNumber];
  NSString *APIPath = [APIBasePath stringByAppendingPathComponent:updateEntryPath];
  // do something
}
like image 41
XJones Avatar answered Nov 14 '22 04:11

XJones