Cross-Platform Swift.

How do you do conditional compilation in Swift? Here’s a self-explanatory snippet:

#if foo
  // ...
#elseif bar
  // ...
#else
  // ...
#endif

But what can be written in the expressions for #if and #elseif?

For one, build configuration options. They’re passed to the compiler using the -D flag.

Here’s one I always define in my project build settings:

Swift Compiler - Custom Flags
  Other Swift Flags
    Debug
      -D DEBUG

And here’s how you would use it in code:

// Pretend timer minutes are seconds in debug
#if DEBUG
  let totalSeconds = totalMinutes
#else
  let totalSeconds = totalMinutes * 60
#endif

The above code lets me test Binaural’s Timer feature without getting old in the process :)

There are two more things that can be used inside the aforementioned conditionals, the function-like os() and arch() constructs.

Here’s how os() can be used to shim a few UIKit/AppKit classes:

// MARK: Typealiases
#if os(iOS)
  import UIKit
  public typealias Responder = UIResponder
  public typealias Image = UIImage
  public typealias Color = UIColor
#elseif os(OSX)
  import AppKit
  public typealias Responder = NSResponder
  public typealias Image = NSImage
  public typealias Color = NSColor
#endif
	
// Now this works across platforms!
let rainImage = Image(named: "Rain")!

I have to say, I was surprised at the amount of view code that I was able to reuse using simple shimming.

Isn’t it annoying how NSView defines alphaValue, while UIView defines alpha? Let’s fix that:

// MARK: Views
#if os(iOS)
  public typealias View = UIView
#elseif os(OSX)
  public class View: NSView {
    public var alpha: CGFloat {
      get {
        return alphaValue
      }
      set {
        alphaValue = newValue
      }
    }
  }
#endif

Note that Apple’s documentation is wrong in saying that os() accepts OS X as an argument - only OSX (no spaces) works. I blame autocorrect.

You can use arch() to conditionally compile based on the target architecture. The accepted values are currently x86_64, arm, arm64, and i386.

As you would expect, you can use &&, ||, and ! to create compound and more elaborate conditionals.

If you want to learn more about how to use shimming effectively, check out the great WWDC 2014 video “Sharing code between iOS and OS X”.

Now go and shim all the things! And if you have any questions, just ask.