如何在 Swift 条件编译语句中检查 iOS 部署目标?
我尝试了以下方法:
#if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_8_0
// some code here
#else
// other code here
#endif
但是,第一个表达式会导致编译错误:
Expected '&&' or '||' expression
如何在 Swift 条件编译语句中检查 iOS 部署目标?
我尝试了以下方法:
#if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_8_0
// some code here
#else
// other code here
#endif
但是,第一个表达式会导致编译错误:
Expected '&&' or '||' expression
TL;博士?> 转至3. 解决方案
Swift 编译器不包含预处理器。相反,它利用编译时属性、构建配置和语言特性来完成相同的功能。出于这个原因,预处理器指令不会在 Swift 中导入。
这就是为什么在尝试使用__IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_8_0
which 是 C 预处理指令时会出错的原因。使用 swift 您不能#if
与诸如<
. 你所能做的就是:
#if [build configuration]
或带条件:
#if [build configuration] && ![build configuration]
再次来自相同的文档:
构建配置包括下表中列出的真假值、命令行标志和平台测试函数。您可以使用 -D <#flag#> 指定命令行标志。
true
和false
:不会帮助我们os(iOS)
或arch(arm64)
> 对您没有帮助,搜索了一下,无法确定它们的定义位置。(也许在编译器本身?)感觉有点像一种解决方法,但确实有效:
现在例如,您可以使用#if iOSVersionMinRequired7
代替__IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_7_0
,当然假设您的目标是 iOS7。
这与在项目中更改 iOS 部署目标版本基本相同,只是不太方便......当然,您可以根据您的 iOS 版本目标使用相关方案进行多重构建配置。
苹果肯定会改进这一点,也许有一些内置的功能,比如os()
......
在 Swift 2.2 中测试
你说的Deployment Target
意思是iOS version
,还是App Target
?如果您有多个版本的应用程序(免费应用程序、付费应用程序......),下面我将提供解决方案,以便您使用不同的应用程序目标。
您可以设置自定义构建配置:
1. 转到您的项目/选择您的目标/构建设置/搜索自定义标志
2. 对于您选择的目标,使用-D
前缀(不带空格)设置您的自定义标志,用于调试和发布
3。为您拥有的每个目标执行上述步骤
要区分目标,您可以执行以下操作:
var target: String {
var _target = ""
#if BANANA
_target = "Banana"
#elseif MELONA
_target = "Melona"
#else
_target = "Kiwi"
#endif
return _target
}
override func viewDidLoad() {
super.viewDidLoad()
print("Hello, this is target: \(target)"
}
你不能在这样的条件编译语句中做到这一点。Swift 不支持 Apple 所称的“复杂宏”。在他们看来,泛型和类型做同样的事情,结果更好。(这是他们发布的链接https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/BuildingCocoaApps/InteractingWithCAPIs.html#//apple_ref/doc/uid/TP40014216-CH8-XID_13)
这是我想出的一个函数,它完成了同样的事情(显然,只需将字符串返回替换为对您有用的任何内容,如布尔值或仅选项本身):
func checkVersion(ref : String) -> String {
let sys = UIDevice.currentDevice().systemVersion
switch sys.compare(ref, options: NSStringCompareOptions.NumericSearch, range: nil, locale: nil) {
case .OrderedAscending:
return ("\(ref) is greater than \(sys)")
case .OrderedDescending:
return ("\(ref) is less than \(sys)")
case .OrderedSame:
return ("\(ref) is the same as \(sys)")
}
}
// Usage
checkVersion("7.0") // Gives "7.0 is less than 8.0"
checkVersion("8.0") // Gives "8.0 is the same as 8.0"
checkVersion("8.2.5") // Gives "8.2.5 is greater than 8.0"
我知道您的问题已经存在了一段时间,但以防万一有人仍在寻找答案,他们应该知道从 Swift 2.0 开始,您可以执行以下操作:
if #available(iOS 8, *) {
// iOS 8+ code
} else {
// older iOS code
}
你可以在这里阅读更多关于它的信息。
我最近在构建一个源代码支持具有不同功能的多个 iOS 和 macOS 版本的库时遇到了这个问题。
我的解决方案是在 Xcode 中使用自定义构建标志,这些标志从实际部署目标中派生出它们的值:
TARGET_IOS_MAJOR = TARGET_IOS_MAJOR_$(IPHONEOS_DEPLOYMENT_TARGET:base)
TARGET_MACOS_MAJOR = TARGET_MACOS_MAJOR_$(MACOSX_DEPLOYMENT_TARGET:base)
参考Others Swift Flags中的那些用户定义的设置,例如:
OTHER_SWIFT_FLAGS = -D$(TARGET_MACOS_MAJOR) -D$(TARGET_IOS_MAJOR)
允许我在我的 Swift 源代码中检查实际的主要操作系统版本,如下所示:
#if os(macOS)
#if TARGET_MACOS_MAJOR_12
#warning("TARGET_MACOS_MAJOR_12")
#elseif TARGET_MACOS_MAJOR_11
// use custom implementation
#warning("TARGET_MACOS_MAJOR_11")
#endif
#elseif os(iOS)
#if TARGET_IOS_MAJOR_15
#warning("TARGET_IOS_MAJOR_15")
#elseif TARGET_IOS_MAJOR_14
#warning("TARGET_IOS_MAJOR_14")
#else
#warning("older iOS")
#endif
#endif
目前我不知道在 SPM 包中是否可以使用类似的方法。这是我将在稍后阶段尝试做的事情。