swiftobjective-cxcodemacosmac-catalyst

Why is TARGET_OS_IPHONE not skipping over the code when building for Mac Catalyst?


I am using the Texture/AsyncDisplayKit library in an app for iOS and macOS Catalyst. It has this known issue on macOS:

https://github.com/TextureGroup/Texture/issues/1549

It basically throws the error Use of undeclared identifier 'CAEAGLLayer' when building for macOS Catalyst. Error comes from this block of code:

// CAEAGLLayer
if([[view.layer class] isSubclassOfClass:[CAEAGLLayer class]]){
_flags.canClearContentsOfLayer = NO;
}

If I comment this code out, then it builds successfully on macOS Catalyst.

So, I figured that I could use the TARGET_OS_IPHONE macro to exclude this code when building for Catalyst:

#if TARGET_OS_IPHONE
      // CAEAGLLayer
      if([[view.layer class] isSubclassOfClass:[CAEAGLLayer class]]){
        _flags.canClearContentsOfLayer = NO;
      }
#endif

However, Xcode still continues to attempt to build this code and then fails.

Why is #if TARGET_OS_IPHONE not excluding this code on macOS Catalyst?

EDIT: While I did find a workaround solution from this link:

https://github.com/nickaroot/Texture/commit/05a486e3275de53f2b0dfb24925fa528e2b610e6

by using #if !TARGET_OS_MACCATALYST instead of #if TARGET_OS_IPHONE, I still want to know why my original way doesn't work? The ! (not) way seems weird.


Solution

  • It is annoying. The problem is that when you choose to build the macOS version of the app by selecting a Mac as the build target, then the definitions of TARGET_OS_MACCATALYST and TARGET_OS_IPHONE are both set to 1. When you select an iOS device or iOS simulator as the build target, then TARGET_OS_MACCATALYST is set to 0 while TARGET_OS_IPHONE is set to 1.

    I suspect Apple did it this way because a Mac Catalyst app is basically an iOS app, just built with a compatibility layer for macOS.

    In my own iOS app that also supports Mac Catalyst, I use #if TARGET_OS_MACCATALYST around code that is only for the macOS version, and I use #if !TARGET_OS_MACCATALYST around code that is only for the iOS version.

    You can see these definitions easily enough. Right-click on TARGET_OS_MACCATALYST and choose "Jump to Definition". You will be taken to the TargetConditionals.h file. Depending on your build target, you will be taken to different parts of that header file where several TARGET_OS_XXX macros are set to 0 or 1 based on the target. Try it for a Mac target then try it for an iOS target and you will see the appropriate definitions.