10

如何在 Swift 条件编译语句中检查 iOS 部署目标?

我尝试了以下方法:

#if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_8_0
    // some code here
#else
    // other code here
#endif

但是,第一个表达式会导致编译错误:

Expected '&&' or '||' expression
4

5 回答 5

12

TL;博士?> 转至3. 解决方案

1. Swift 中的预处理

根据有关预处理指令的 Apple 文档

Swift 编译器不包含预处理器。相反,它利用编译时属性、构建配置和语言特性来完成相同的功能。出于这个原因,预处理器指令不会在 Swift 中导入。

这就是为什么在尝试使用__IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_8_0which 是 C 预处理指令时会出错的原因。使用 swift 您不能#if与诸如<. 你所能做的就是:

#if [build configuration]

或带条件:

#if [build configuration] && ![build configuration]

2.条件编译

再次来自相同的文档

构建配置包括下表中列出的真假值、命令行标志和平台测试函数。您可以使用 -D <#flag#> 指定命令行标志。

  • truefalse:不会帮助我们
  • 平台测试功能os(iOS)arch(arm64)> 对您没有帮助,搜索了一下,无法确定它们的定义位置。(也许在编译器本身?)
  • 命令行标志:我们走了,这是您可以使用的唯一选项...

3.解决方案

感觉有点像一种解决方法,但确实有效: 其他 Swift 标志

现在例如,您可以使用#if iOSVersionMinRequired7代替__IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_7_0,当然假设您的目标是 iOS7。

这与在项目中更改 iOS 部署目标版本基本相同,只是不太方便......当然,您可以根据您的 iOS 版本目标使用相关方案进行多重构建配置。

苹果肯定会改进这一点,也许有一些内置的功能,比如os()......

于 2014-06-24T22:30:16.077 回答
7

在 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)"
}
于 2016-04-08T14:37:46.453 回答
0

你不能在这样的条件编译语句中做到这一点。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"
于 2014-06-23T17:47:03.973 回答
0

我知道您的问题已经存在了一段时间,但以防万一有人仍在寻找答案,他们应该知道从 Swift 2.0 开始,您可以执行以下操作:

if #available(iOS 8, *) {
    // iOS 8+ code
} else {
    // older iOS code
}

你可以在这里阅读更多关于它的信息。

于 2016-07-28T11:40:01.810 回答
0

我最近在构建一个源代码支持具有不同功能的多个 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 包中是否可以使用类似的方法。这是我将在稍后阶段尝试做的事情。

于 2022-02-13T10:55:40.837 回答