Converting Complex Objective-C Macros to Swift Functions

The question of how to convert #define macros from Objective-C to Swift is explained fairly simply in the Apple developer documentation on the subject. For simple macros, it’s a matter of rewriting them as global constants. In fact, if you’re using the hybrid Objective-C — Swift approach to writing your app, Swift sees those simple macros and automatically makes them available to your Swift code. I also gave some tips on the alternative to Objective-C macros a while back.

Where we run into trouble is when we need to port complex Objective-C macros to Swift. According to the same documentation from Apple,

Complex macros are used in C and Objective-C but have no counterpart in Swift.

Yikes!

Thankfully there is a silver lining after that scary first sentence:

Complex Macros Explanation

In Swift, you can use functions and generics to achieve the same results without any compromises.

That makes sense, actually! Complex Objective-C macros tend to look a lot like functions, so the transition to Swift was straightforward in a case I ran across recently.

Two Examples:

A simple example

What could we do in Swift to convert an Objective-C macro that looks something like this?

One thing we could do is write a function that produces the same thing:

A little more complicated

An example situation that came to me on Twitter took the form of converting a macro that was a little more complicated than the simple example just presented. The input to the complex macro was a color, represented as a hexadecimal value, along with an alpha, represented as a float. The output? A UIColor instance based on some bitwise manipulations to that hex value.

I’ve created a GitHub example if you’d like to play around with everything. The relevant code is reproduced below…

The macro form looked like this:

Rewriting it as a Swift function:

The main thing to keep in mind is that the output of the macro/function is the focus. The internals could change to better-adapt to Swift’s features if you desire. If the macro was ugly inside, make it nice in Swift!

Where should the function go?

  • For organization’s sake, you could create a new .swift file and place the function inside it at the global level. This would provide the most convenient transition for your Objective-C to Swift conversion, because #defines were available wherever you imported the Objective-C header file.
  • Alternatively, you could encapsulate the function in a class/struct/enum.

Wrapping up

With the power of Swift functions and the ability to even declare and use them globally, converting complex macros to a better Swift alternative is much less daunting than you might expect.