Jos*_*nez 39 iphone macos xcode conditional-compilation
我正在开发一个包含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,即使它正在编译iOS 3.2,它仍然会使用新的常量,这似乎是不正确的.
在此先感谢您的帮助!
Ste*_*her 66
你在观察中犯了一个错误.:)
TARGET_OS_MAC在构建Mac或iPhone应用程序时将为1.你是对的,对于这种事情来说,这是无用的.
但是,TARGET_OS_IPHONE在构建Mac应用程序时为0.TARGET_OS_IPHONE为此我一直在我的标题中使用.
像这样:
#if TARGET_OS_IPHONE
// iOS code
#else
// OSX code
#endif
Run Code Online (Sandbox Code Playgroud)
这是一个很棒的图表:http: //sealiesoftware.com/blog/archive/2010/8/16/TargetConditionalsh.html
"正确的做法就是使用更新的常量,因为如果查看标题,你会发现它们被声明等同于enum中的旧标题,这意味着新常量甚至可以在旧版本中使用(两个常量)编译成相同的东西,因为枚举被编译到应用程序中,他们无法在不破坏二进制兼容性的情况下进行更改..不这样做的唯一原因是,如果您需要继续构建旧的SDK(这是一个不同于支持旧版本,您可以在针对较新的SDK进行编译时执行此操作.
如果你真的想根据操作系统版本使用不同的标志(因为新版本实际上添加了新功能,而不是只重命名常量),那么你可以做两件明智的事情,上面的宏都没有完成:
要始终使用旧标志,除非允许的最小版本大于它们引入的版本(如下所示):
#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 40000 || __MAC_OS_X_VERSION_MIN_REQUIRED >= 1060)
NSDataReadingOptions options = NSDataReadingMapped;
#else
NSDataReadingOptions options = NSMappedRead;
#end
Run Code Online (Sandbox Code Playgroud)有条件地只使用只能在新版本上构建的新值,并在代码中编译以确定运行时的标志,以支持两个版本的构建:
#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
Run Code Online (Sandbox Code Playgroud)请注意,如果你真的在进行这种比较,你会想要隐藏[[UIDevice currentDevice] systemVersion] compare:@"4.0"]某个地方的结果.您通常还希望使用弱链接而不是进行版本比较来显式测试功能,但这不是枚举的选项.
要使用的宏在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
Run Code Online (Sandbox Code Playgroud)
由于这里的所有内容都是"Mac OS X变体",TARGET_OS_MAC因此在这种情况下无用.要专门为macOS编译,例如:
#if !TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR && !TARGET_OS_EMBEDDED
// macOS-only code
#endif
Run Code Online (Sandbox Code Playgroud)
更新:现在已经TARGET_OS_OSX为macOS专门定义了更新的标题(Xcode 8+?).(h/t @OldHorse),所以这应该工作:
#if TARGET_OS_OSX
// macOS-only code
#endif
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
20429 次 |
| 最近记录: |