44

我正在开发一个包含共享代码的 Mac 应用程序和 iPad 应用程序的项目。如何使用条件编译开关从 iPhone 项目中排除特定于 Mac 的代码,反之亦然?我注意到TARGET_OS_IPHONEandTARGET_OS_MAC都是 1,所以它们总是正确的。是否有另一个我可以使用的开关,它只会在为特定目标编译时返回 true?

在大多数情况下,我已经通过移动#include <UIKit/UIKit.h>#include <Cocoa/Cocoa.h>进入两个项目的预编译头文件来使文件进行协作。我正在共享模型和一些从 RSS 提要和 Evernote 获取数据的实用程序代码。

特别是,与[NSData dataWithContentsOfURL:options:error:]iOS 4 和 Mac OS 10.6 相比,该函数为选项参数 iOS 3.2 和更早版本以及 Mac OS 10.5 和更早版本采用不同的常量。我使用的条件是:

#if (TARGET_OS_IPHONE && (__IPHONE_OS_VERSION_MAX_ALLOWED > __IPHONE_3_2)) || (TARGET_OS_MAC && (MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_5))

这似乎可行,但我想确保这是防弹的。我的理解是,如果 Mac 版本设置为 10.6,而 iOS 版本设置为 3.2,即使是为 iOS 3.2 编译,它仍然会使用新的常量,这似乎不正确。

提前感谢您的帮助!

4

4 回答 4

71

你的观察有误。:)

TARGET_OS_MAC构建 Mac 或 iPhone 应用程序时将为 1。你说得对,这种东西根本没用。

但是,TARGET_OS_IPHONE在构建 Mac 应用程序时为 0。TARGET_OS_IPHONE为此,我一直在我的标题中使用。

像这样:

#if TARGET_OS_IPHONE
// iOS code
#else
// OSX code
#endif

这是一个很好的图表: http ://sealiesoftware.com/blog/archive/2010/8/16/TargetConditionalsh.html

于 2010-07-06T00:39:54.163 回答
8

“正确的做法是使用较新的常量,因为如果您查看标题,您会发现它们被声明为与枚举中的旧常量等效,这意味着即使在旧版本上新常量也可以工作(两个常量编译成相同的东西,并且由于枚举被编译到应用程序中,它们无法在不破坏二进制兼容性的情况下进行更改。不这样做的唯一原因是如果您需要继续构建旧的 SDK(这与支持较旧的版本,您可以在针对较新的 SDK 进行编译时执行此操作)。

如果您真的想根据操作系统版本使用不同的标志(因为新版本实际上添加了新功能,而不是仅仅重命名一个常量),那么您可以做两件明智的事情,但上述宏都不能完成:

  1. 要始终使用旧标志,除非允许的最低版本大于它们引入的版本(类似这样):

    #if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 40000 || __MAC_OS_X_VERSION_MIN_REQUIRED >= 1060)
      NSDataReadingOptions  options = NSDataReadingMapped;
    #else
      NSDataReadingOptions  options = NSMappedRead;
    #end
    
  2. 有条件地仅在只能在新版本上使用的构建中使用新值,并在代码中编译以确定支持两个版本的构建在运行时的标志:

    #if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 40000 || __MAC_OS_X_VERSION_MIN_REQUIRED >= 1060)
      NSDataReadingOptions  options = NSDataReadingMapped;
    #else
      NSDataReadingOptions  options;
      if ([[UIDevice currentDevice] systemVersion] compare:@"4.0"] != NSOrderedAscending) {
         options = NSDataReadingMapped;
      } else {
        options = NSMappedRead;
      }
    #end
    

请注意,如果您实际上经常进行此比较,您可能希望将结果存储在[[UIDevice currentDevice] systemVersion] compare:@"4.0"]某处。您通常还希望使用弱链接等功能来显式测试功能,而不是进行版本比较,但这不是枚举的选项。

于 2010-07-05T18:42:34.440 回答
8

要使用的宏在 SDK 头文件中定义TargetConditionals.h。取自 10.11 SDK:

TARGET_OS_WIN32           - Generated code will run under 32-bit Windows
TARGET_OS_UNIX            - Generated code will run under some Unix (not OSX) 
TARGET_OS_MAC             - Generated code will run under Mac OS X variant
   TARGET_OS_IPHONE          - Generated code for firmware, devices, or simulator 
      TARGET_OS_IOS             - Generated code will run under iOS 
      TARGET_OS_TV              - Generated code will run under Apple TV OS
      TARGET_OS_WATCH           - Generated code will run under Apple Watch OS
   TARGET_OS_SIMULATOR      - Generated code will run under a simulator
   TARGET_OS_EMBEDDED       - Generated code for firmware

由于这里的一切都是“Mac OS X 变体”,TARGET_OS_MAC因此在这种情况下没有用。专门为 macOS 编译,例如:

#if !TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR && !TARGET_OS_EMBEDDED
    // macOS-only code
#endif

更新:较新的标头(Xcode 8+?)现在TARGET_OS_OSX专门为 macOS 定义。(h / t @OldHorse),所以这应该工作:

#if TARGET_OS_OSX
 // macOS-only code
#endif
于 2016-07-05T16:00:12.197 回答
2

要使用的宏集现在包括 TARGET_OS_OSX:

    TARGET_OS_WIN32           - Generated code will run under 32-bit Windows
    TARGET_OS_UNIX            - Generated code will run under some Unix (not OSX) 
    TARGET_OS_MAC             - Generated code will run under Mac OS X variant
       TARGET_OS_OSX          - Generated code will run under OS X devices
       TARGET_OS_IPHONE          - Generated code for firmware, devices, or simulator
          TARGET_OS_IOS             - Generated code will run under iOS 
          TARGET_OS_TV              - Generated code will run under Apple TV OS
          TARGET_OS_WATCH           - Generated code will run under Apple Watch OS
             TARGET_OS_BRIDGE          - Generated code will run under Bridge devices
       TARGET_OS_SIMULATOR      - Generated code will run under a simulator
       TARGET_OS_EMBEDDED       - Generated code for firmware

似乎适用于 macOS 代码的条件编译。

于 2017-03-08T16:10:16.327 回答