保持NSUserActivity与Xcode 9向后兼容

时间:2018-08-31 15:10:30

标签: ios swift xcode xcode10

使用Xcode 10(测试版6),我可以轻松编写并运行以下代码:

import Intents

func test() {

    let activity = NSUserActivity(activityType: "com.activtiy.type")

    activity.title = "Hello World"
    activity.isEligibleForSearch = true
    activity.isEligibleForHandoff = false

    if #available(iOS 12.0, *) {
        activity.isEligibleForPrediction = true
        activity.suggestedInvocationPhrase = "Say something"
    }

    print(activity)
}

从iOS 12开始,已经添加了.isEligibleForPredictions.suggestedInvocationPhrase属性,因此Xcode 10可以使用if #available条件使代码本身向后兼容。

但是,我想确保此代码与Xcode的早期版本向后兼容。在Xcode 9中运行时,出现以下错误:

if #available(iOS 12.0, *) {
        // ERROR: Value of type 'NSUserActivity' has no member 'isEligibleForPrediction'
        activity.isEligibleForPrediction = true

        // ERROR: Value of type 'NSUserActivity' has no member 'suggestedInvocationPhrase'
        activity.suggestedInvocationPhrase = "Say something"
    }

这似乎是因为#available宏实际上是在运行时解析的,因此所包含的所有代码仍需要成功编译。

在为iOS 11构建或使用Xcode 9时,有没有办法告诉编译器忽略这两行代码?

2 个答案:

答案 0 :(得分:1)

Xcode 10使用Swift 4.2,而Xcode 9使用Swift 4.1。因此,您可以在编译时使用该知识:

func test() {
    let activity = NSUserActivity(activityType: "com.activtiy.type")

    activity.title = "Hello World"
    activity.isEligibleForSearch = true
    activity.isEligibleForHandoff = false

    #if swift(>=4.2) // compile-time check
    if #available(iOS 12.0, *) { // run-time check
        activity.isEligibleForPrediction = true
        activity.suggestedInvocationPhrase = "Say something"
        predictionApiAvailable = true
    }
    #endif

    print(activity)
}

(此答案假设您正在Xcode 10上使用Swift 4.2。)

答案 1 :(得分:1)

您正确使用的可用性条件(如果#available)是在运行时评估的,但是编译器将使用此信息来提供编译时的安全性(如果您正在调用API,则会警告您最小部署目标不存在。

要有条件地编译代码,必须使用Conditional Compilation Block

#if compilation condition
statements
#endif

要有条件地基于Xcode版本构建代码,可以在构建设置(-D swift编译标志)中包括Active Compilation Condition,它的名称是根据Xcode版本动态创建的。然后将其用作编译条件。 Xcode已经提供了构建设置XCODE_VERSION_MAJOR,可以将其解析为当前的Xcode版本(例如,对于Xcode 9,为0900)。因此,您可以添加一个名称为XC​​ODE_VERSION _ $(XCODE_VERSION_MAJOR)的活动编译条件,该条件将解析为Xcode 9的标志XCODE_VERSION_0900。

enter image description here

然后,您可以使用以下条件有条件地编译代码:

#if XCODE_VERSION_0900
statements
#endif

我有一个示例项目here