objC Preprocessor NSString Macro - objective-c

I have a problem to create a preprocessor macro function, that concatenates two Strings and "return" a NSString (#"...") value.
Here is what I tried:
#define ObjectKeyMake(NAME) #"com.test.##NAME"
if I print the result from a call I get:
NSLog(#"%#", ObjectKeyMake(foo)); // com.test.##NAME
so my question is: How can i concatenate 2 Strings in a preprocessor macro and "return" a NSString (#"..") ?
and no I can't use #define ObjectKeyMake(NAME) [#"com.test." stringByAppendingString: NAME] because i need a compile-time constant.

You can take advantage of the fact that the compiler combines string literals that are next to each other, like this:
NSString* greeting = #"Hello, " "world";
The macro implementation would look like this:
#define ObjectKeyMake(NAME) (#"com.test." #NAME)

#define ObjectKeyMake(NAME) #"com.test."#NAME

Related

Using macros for string concatenation

I want to create macro that receives 2 arguments: NSString and ObjCBool and returns NSString.
I'm not familiar a lot with macros, anyway this is what I did so far:
#define fooOne(url)\
#"1111111" url
#define fooTwo(url)\
#"2222222" url
#define root(url, flag)\
if(!flag)fooOne(url)\
else fooTwo(url)
Here I have 2 problems:
1) when I call fooOne as:
NSString *url = #"zzz";
NSLog(#"%#", fooOne(url));
// expected log should be: "1111111 zzz"
I get error: Expected ')'
2) When I call root(url, flag) as:
BOOL flag = YES;
NSString *url = #"zzz";
NSLog(#"%#", root(url, flag));
// expected log should be: "2222222 zzz"
I get an error: Expected expression
please help,
Compile-time string concatenation only works with string literals. At compile time #"hello, " #"world" is combined into a new string literal #"hello, world". This doesn't work with strings contained in variables — #"blabla" url is not a valid expression, even if url contains a string literal at runtime. You would have to call your macros with the literal inside: fooOne(#"zzz"), which would expand to #"blabla" #"zzz".
If you want to combine strings at runtime, you'll need to use +[NSString stringWithFormat:], or append the strings.

OBJ C Macro by Stringname

I try to get a macro by NSString value:
Example:
#define FOO1 NSLocalizedString (#"TEXT",#"COMMENT")
#define FOO2 NSLocalizedString (#"TEXT2",#"COMMENT2")
in .m File:
NSString *macroName = [NSString stringWithFormat:"FOO%d",1];
label.text = MACROBYNAME(macroName);
is there a way to do something like this?
Another approach to solution is a Switch-Case in the macro like this:
#define FOOSELECTOR(x) Switch x
case "FOO1"
NSLocalizedString (#"TEXT",#"COMMENT")
break;
case "FOO2"
NSLocalizedString (#"TEXT2",#"COMMENT2")
break;
or something like that... any Ideas?
Okay, I'll bite and make this an answer instead of a comment:
No, it's not possible. There's no way to do what you want to do.
Macros are evaluated during compile time, that's when you hit cmd-b in Xcode. Functions are called during runtime. That's when the program is run, possibly years after compilation.
Furhtermore, why do you want to do it? What's wrong with
NSString *localizedString = NSLocalizedString (#"TEXT",#"COMMENT");
label.text = [NSString stringWithFormat:#"%#%d", localizedString, 1];
?

Stringizing ObjectiveC Strings at runtime

I'm trying to stringize an Objective C string at runtime.
Is it possible to use the stringizing operator to do this? I realize it's a preprocessed macro, but could I combine it with a function that returned a char*?
This is what I'd like to do is..
#define strthis(x) #x
char *itsstringized = strthis([#"my string" UTF8String]);
printf("%s", itsstringized);
Result:
"my string"
not
my string
Do you want something like this?
Pass a string to a method and it will return the string enclosed in a quotes.
-(NSString *)stringizedString(NSString *)str{
return [NSString stringWithFormat:#"\"%#\"", str];
}
You sure can! Try this macro out:
#define QUOTEIFY(input) #("\"" #input "\"")
#define QUOTEIFY_STRING(input) #("\"" input "\"")
Usage:
NSLog(QUOTEIFY(Hello World!)); // notice I didn't quote what's inside the brackets.
// or, if you prefer:
NSLog(QUOTEIFY_STRING("Hello, World!"));

#define macro does not take variable values

I have created #define statement in project's pch file so it can be seen in all files in the project, the statement is: #define MYURL(x,y) #"http://internal-sps/providers.aspx?category=(a)&regionID=(y)"
however, I use this macro in any file inside the project like this:
NSString *url = MYURL(#"category1",#"3");
then NSLog(#"%#", url); the console shows this:
http://internal-sps/providers.aspx?category=(a)&regionID=(y) not the actual values.
how can i get the actual values for this macro ?
Change:
#define MYURL(x,y) #"http://internal-sps/providers.aspx?category=(a)&regionID=(y)"
to:
#define MYURL(x,y) "http://internal-sps/providers.aspx?category=(a)&regionID=("y")"
and use your macro like this:
NSString *url = #MYURL("category1","3");
Note: if that a is actually meant to be an x then it would be:
#define MYURL(x,y) "http://internal-sps/providers.aspx?category=("x")&regionID=("y")"

Are strings defined as constants not NSStrings?

I have a constant defined as:
#define BEGIN_IMPORT_STRING #"Importing Hands!";
But I get an error when I try to concat with:
NSString *updateStr = [NSString stringWithFormat:#"%#%#", BEGIN_IMPORT_STRING, #" - Reading "];
This doesn't happen if I replace it with a string literal
NSString *updateStr = [NSString stringWithFormat:#"%#%#", #"foo", #" - Reading "];
Or a local string
NSString *temp = #"foo";
NSString *updateStr = [NSString stringWithFormat:#"%#%#", temp, #" - Reading "];
You need to remove the semicolon from your #define:
#define BEGIN_IMPORT_STRING #"Importing Hands!"
To the compiler, the resulting line looks like this:
NSString *updateStr = [NSString stringWithFormat:#"Importing Hands!";, #" - Reading "];
Replace
#define BEGIN_IMPORT_STRING #"Importing Hands!";
with
#define BEGIN_IMPORT_STRING #"Importing Hands!"
This is because compiler in your case replaces all occurrences of BEGIN_IMPORT_STRING with #"Importing Hands!";
Aside from the accepted answer (remove semicolon), note that:
#"Foo" is an NSString. You can even send it a message.
#define FOO #"Foo" is a preprocessor macro, not a constant. It's a typing shortcut.
Though macros aren't an uncommon way to avoid retyping the same string, they're an unfortunate holdover. Essentially, they're playing games that aren't necessary anymore.
For repeated strings, I prefer:
static NSString *const Foo = #"Foo;
The const portion of this definition ensures that the pointer is locked down, so that Foo can't be made to point to a different object.
The static portion restricts the scope to the file. If you want to access it from other files, remove the static and add the following declaration to your header file:
extern NSString *const Foo;
Should you be using
NSLocalizedString(#"Importing Hands!", #"Message shown when importing of hands starts");
?
I put it as an answer because this looks like something you would not want to have to go and redo through all your code.