使用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时,有没有办法告诉编译器忽略这两行代码?
答案 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)。因此,您可以添加一个名称为XCODE_VERSION _ $(XCODE_VERSION_MAJOR)的活动编译条件,该条件将解析为Xcode 9的标志XCODE_VERSION_0900。
然后,您可以使用以下条件有条件地编译代码:
#if XCODE_VERSION_0900
statements
#endif
我有一个示例项目here