其条件编译使用到Mac和iPhone的特定代码之间切换?

问题描述 投票:39回答:4

我的工作,包括在Mac应用程序和共享代码的iPad应用的项目。如何使用条件编译开关从iPhone项目,反之亦然排除Mac特有的代码?我注意到,TARGET_OS_IPHONETARGET_OS_MAC都为1,所以他们都总是如此。是否有另一种开关编译为一个特定的目标时,我可以使用,将只返回true?

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

特别地,[NSData dataWithContentsOfURL:options:error:]函数取为options参数的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,将仍然使用,即使它编译为iOS 3.2,这似乎是不正确的新常量。

在此先感谢您的帮助!

iphone xcode macos conditional-compilation
4个回答
65
投票

你让你的看法是错误的。 :)

TARGET_OS_MAC将是1号楼一台Mac或iPhone应用程序时。你说得对,它是这样的事情完全无用。

然而,建立在Mac应用程序时TARGET_OS_IPHONE为0。我在标题中使用TARGET_OS_IPHONE所有的时间用于这一目的。

像这样:

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

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


8
投票

“正确的事情做的仅仅是使用新的常量,因为如果你看头部,你就会看到他们的声明等同于旧的枚举,这意味着新常量会甚至工作在老版本(包括常量编译为同样的事情,而且由于枚举被编译到他们不能改变不破坏二进制兼容性的应用程序),唯一的理由不这样做,就是如果你需要继续建设agains旧的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"]的结果。你可能还需要明确地测试使用像弱连接的,而不是做版本进行比较的功能,但这并不是对枚举的选项。


7
投票

宏使用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

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的代码进行条件编译。

© www.soinside.com 2019 - 2024. All rights reserved.