Questions › Converting an Objective-C #define macro to Swift

I've got a macro in an Objective-C project that shortens typing a long reference:

#define CURRENT_USER DataConnector.sharedInstance.currentUser

This allows me to pass CURRENT_USER in place of ^ to reference the current user.

How would I replicate this in Swift? I've tried this suggested let solution, but that appears actually creates a variable which is immutable. Is using var appropriate instead? What if the #define was instead:

#define CONST_STR = static NSString* const

...which can be used like:

CONST_STR kXXSomeConstant = @"a constant string";

can the Swift let (or var?) solution be used in the same fashion?

Comments :

No, I'm not asking how to make a constant string in Swift. Please read the question thanks.

Hamish replied

Macros are horrible. They're not type-safe and can make debugging a nightmare. If you're really using a a particular line of code often enough to make a macro of it, you're probably doing something wrong in the first place. If I were re-writing my code in Swift, I'd be trying to find a solution that isn't a 'Swift version of a macro'.

@originaluser2 now THAT I can get behind. I agree, and I don't actually intend to use this anywhere, but I definitely want to understand if there's a way to do it in Swift, if not, and why.

aug2uag replied

using #define is bad practice, should be using const that makes it self-explanatory how to use


2 Answers :
Duncan C answered

It's my understanding that the Swift compiler does not use the C preprocessor, so macros are simply not possible. Like the other commenters, I would suggest finding a more swift-like way to handle this situation. Macros have a serious down-side, as pointed out by @originaluser2 in his/her comment. (Not to mention the fatal flaw of being completely unsupported in Swift.)

brandonscript replied
Accepted, because you actually answered the question I asked ;);
David Berry answered

You should be able to use a var with a custom getter:

var CURRENT_USER : User {
    return DataConnector.sharedInstance.currentUser
}
brandonscript replied
Right, I realize I can do that, but it's still evaluating it; the Objective-C #define actually creates a compiler macro that is replaced at compile-time, no?;
David Berry replied
Yes, but the overhead of a single call to this simple function (which almost certainly optimizes out to no call at all) compared to the overhead of evaluating DataConnector.sharedInstance.currentUser is pretty negligible.;
ishaq replied
Swift doesn't have support for preprocessor macros, in absence of those, this is pretty much the best option.;
mipadi replied
@remus: Your Objective-C macro expands to a method call every time it is used, too.;
Duncan C replied
Macros are purely convenience. They are often less efficient at runtime than function calls because as David says, they just copy-paste the original code inline. Plus the total lack of type-safety and inability to debug make them painful to use (as mentioned by originaluser2.) I'm frankly glad Swift doesn't support them. Good riddance to bad rubbish, as the expression goes.;