保持 NSUserActivity 向后兼容 Xcode 9 [英] Keeping NSUserActivity backwards compatible with 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屋!