Advertisement

Testing for OS X vs iOS

Yesterday, I was messing around building shared NSLayoutConstraint code to be used across iOS and OS X. I put in a few #if TARGET_OS_MAC directives, assuming they'd just work.

They didn't.

Turns out that you should always check for TARGET_OS_IPHONE first, before TARGET_OS_MAC because the latter is true on the iPhone but the former is not on OS X.

Here are some of the most common checks suggested to me yesterday as I messed with this dilemma.

  • #if TARGET_OS_MAC

  • #if TARGET_OS_IPHONE

  • #if TARGET_IPHONE_SIMULATOR

  • #if TARGET_OS_EMBEDDED

  • #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED)

  • #if defined(__IPHONE_OS_MIN_VERSION_REQUIRED)

And here are the results of running them on the Simulator, iPhone device and OS X:

SIMULATOR
Target OS Mac
Target OS iPhone
No Target OS Embedded
Target iPhone Simulator
Mac OS X Version Min Required is NOT defined
iPhone OS X Version Min Required is NOT defined

PHONE
Target OS Mac
Target OS iPhone
Target OS Embedded
No Target iPhone Simulator
Mac OS X Version Min Required is NOT defined
iPhone OS X Version Min Required is NOT defined

OS X
Target OS Mac
No Target OS iPhone
No Target OS Embedded
No Target iPhone Simulator
Mac OS X Version Min Required is defined
iPhone OS X Version Min Required is NOT defined

Since I was most interested in determining whether to use NSBox/NSView vs UIView, my solution ended up looking like this:

#if TARGET_OS_IPHONE
#define VIEW_CLASS UIView
#elif TARGET_OS_MAC
#define VIEW_CLASS NSView
#endif

This approach ensured that the iPhone platform triggered first, and then the second check mandated OS X. This created definitions that allowed my code to successfully compile and execute cross-platform.

Thanks Gwynne Raskind and everyone else in #iphonedev