代码之家  ›  专栏  ›  技术社区  ›  Jose Ibanez

使用哪个条件编译在Mac和iPhone特定代码之间切换?

  •  39
  • Jose Ibanez  · 技术社区  · 14 年前

    我正在从事一个项目,其中包括一个Mac应用程序和一个共享代码的iPad应用程序。如何使用条件编译开关从iPhone项目中排除Mac特定代码,反之亦然?我注意到了 TARGET_OS_IPHONE TARGET_OS_MAC 都是1,所以都是真的。我是否可以使用另一个开关,它只在为特定目标编译时返回true?

    #include <UIKit/UIKit.h> #include <Cocoa/Cocoa.h> 到两个项目的预编译头中。我正在分享模型和一些从RSS提要和Evernote获取数据的实用程序代码。

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

    #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,那么即使是为ios3.2编译,它仍然会使用新的常量,这似乎是不正确的。

    提前感谢您的帮助!

    4 回复  |  直到 14 年前
        1
  •  69
  •   Steven Fisher    11 年前

    你在观察中犯了一个错误

    TARGET_OS_MAC

    然而, TARGET_OS_IPHONE 生成Mac应用程序时为0。我用 目标手机 为了这个目的一直在我的头上。

    这样地:

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

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

        2
  •  8
  •   Louis Gerbarg    14 年前

    如果您确实希望基于操作系统版本使用不同的标志(因为新版本实际上添加了新的功能,而不仅仅是重命名常量),那么您可以做两件明智的事情,上面的宏都不能完成这两件事:

    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"] 在某个地方。您通常还希望使用弱链接之类的方法来显式测试特性,而不是进行版本比较,但这不是枚举的选项。

        3
  •  8
  •   Demitri    6 年前

    要使用的宏在SDK头文件中定义 TargetConditionals.h

    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
    
        4
  •  2
  •   OldHorse    7 年前

    要使用的宏集现在包括TARGET\u OS\u 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