保持 NSUserActivity 向后兼容 Xcode 9 [英] Keeping NSUserActivity backwards compatible with Xcode 9

查看:32
本文介绍了保持 NSUserActivity 向后兼容 Xcode 9的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用 Xcode 10 (beta 6) 我可以毫无问题地编写和运行以下代码:

import Intents功能测试(){让活动 = NSUserActivity(activityType: "com.activtiy.type")activity.title = "你好世界"activity.isEligibleForSearch = trueactivity.isEligibleForHandoff = false如果#available(iOS 12.0,*){activity.isEligibleForPrediction = trueactivity.suggestedInvocationPhrase = "说点什么"}打印(活动)}

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

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

if #available(iOS 12.0, *) {//错误:NSUserActivity"类型的值没有成员isEligibleForPrediction"activity.isEligibleForPrediction = true//错误:'NSUserActivity' 类型的值没有成员 'suggestedInvocationPhrase'activity.suggestedInvocationPhrase = "说点什么"}

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

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

解决方案

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

对于有条件地编译代码,您必须使用

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

#if XCODE_VERSION_0900声明#万一

我有一个示例项目这里

Using Xcode 10 (beta 6) I am able to write and run the following code with no trouble:

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)
}

As of iOS 12 the .isEligibleForPredictions and .suggestedInvocationPhrase properties have been added, so Xcode 10 can keep the code itself backwards compatible using the if #available conditional.

However, I want to ensure this code is backwards compatible with earlier versions of Xcode. When run in Xcode 9, I get the following errors:

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"
    }

This appears to be because the #available macro is actually resolved at runtime, therefore all code contained still needs to be compiled successfully.

Is there a way for me to tell the compiler to just ignore these two lines of code when building for iOS 11, or using Xcode 9?

解决方案

The Availability Condition (if #available) you are using as you correctly noted is evaluated at run-time, but the compiler will use this information to provide compile-time safety (It will will warn you if you are calling an API that does not exist min deployment target).

For conditionally compiling code you must use Conditional Compilation Block

#if compilation condition
statements
#endif

To conditionally build your code based on the Xcode version you can include a Active Compilation Condition in the build settings (a -D swift compile flag) that its name is dynamically created based on the Xcode version. Then use this as compilation condition. Xcode already provides the build setting XCODE_VERSION_MAJOR that resolves to the current Xcode version( e.g. 0900 for Xcode 9). So you can add an an Active Compilation Condition with name XCODE_VERSION_$(XCODE_VERSION_MAJOR) that will resolve to the flag XCODE_VERSION_0900 for Xcode 9.

Then you can conditionally compile your code using:

#if XCODE_VERSION_0900
statements
#endif

I have an example project here

这篇关于保持 NSUserActivity 向后兼容 Xcode 9的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆