Swift Alternative to Objective-C Macros
I’ve previously written about using enumerations in Swift to encapsulate special values that could end up falling into the “magic string” category if they were to simply be scattered in-line throughout your code. The primary example I proposed for such a “magic string” replacement was Storyboard Segue Identifiers. These special identifiers have such a specific purpose that felt to me like a natural fit to create a Type in the form of an enumeration (which I called SegueIdentifier) to group them all together in one place so that I could easily find them and modify them, should I ever need to do so.
I still like that solution for groups of things, but it’s a lot of “ceremony” to use enumerations for encapsulating everything that may have been implemented as a macro expression or a static global constant in Objective-C.
I ran across this in the Swift developer documentation that I think will be of help to folks who want to avoid “magic values” throughout their code, but don’t want to employ enumerations where they’re not the best fit. Here’s a snippet:
So there you have it, folks! One easy alternative to your former #define habits when you’re working in Swift is to simply declare a constant (using the let keyword) instead. The word “constant” is key — the last thing you want to do is declare a variable in some global scope (using the var keyword) where the value of the identifier could be changed somehow, if even by accident.
Organizing #define Replacement Constants
The question that naturally comes next is, “Where do I declare a constant that I’m using to replace a #define?”
The answer is not black and white — a few factors play into your decision of where to declare them.
In general, I would probably declare such a constant in the location that’s closest to the context in which it is used. Here are a few examples to consider:
- If it’s only going to be used in a single function, it’s reasonable to declare the constant locally at the top of that function, or anywhere near where it will be used.
- If it’s only used in a single class/struct, perhaps declaring it at the top of that class/struct is a good idea.
- If it’s going to be a value that’s used in multiple classes/structs, it may be time to create a new .swift file and place it there so that you can find it again.
- Start with a very small scope, and as that constant broadens in its usage throughout your project, gradually move it to more and more globally visible locations.
Using a globally-defined constant is exactly what I did for checking the iOS version number of a user’s device. I simply created a new file called “iOSVersions.swift”, placed my global constant definitions in it, and was able to reference those constant names everywhere in my project that I needed to perform conditional logic based on the iOS version number.
A simple Swift alternative to a #define macro in Objective-C it to define a constant at a scope that’s appropriate for where you plan to use that constant.
Originally published at www.andrewcbancroft.com on October 1, 2014.