什么是“Swift 语言版本”Xcode 设置?因为它仍然使用旧版本集构建更新的 Swift 代码

Posted

技术标签:

【中文标题】什么是“Swift 语言版本”Xcode 设置?因为它仍然使用旧版本集构建更新的 Swift 代码【英文标题】:What is the "Swift Language Version" Xcode setting for? Because it still builds newer Swift code with an older version set 【发布时间】:2020-05-27 08:13:09 【问题描述】:

我正在使用将“Swift 语言版本”设置为“Swift 4”的 Xcode 项目构建源代码。即使有了这个集合,该项目也会构建 Swift 5.1 源代码,例如,隐式返回和使用新的 isMultiple(of:) 方法的 Swift 5 源代码。

即使将“Swift 语言版本”设置为“Swift 4”或“Swift 4.2”,Swift 5 和 5.1 代码仍然有效

只有在运行#elseif swift(>=4.1) 语句时才会出现差异(代码来自https://***.com/a/46080904/414415)。这些结果输出了它们的预期结果。

但是,我想知道,当构建设置明确指出 Swift 4 时,我的 Swift 5 源代码如何成功编译?如果设置没有改变我可以使用的 Swift 版本,它实际上做了什么?

【问题讨论】:

“它实际上是做什么的?”用例与您正在做的事情大致相反,即您来自早期版本的 Xcode,例如Swift 4.2,以及在 Swift 5.1 的 this 版本的 Xcode 中合法的东西不再合法。因此,在这种情况下,您可以将目标语言版本设置为 Swift 4.2,直到您准备好将其迁移到 Swift 5。 【参考方案1】:

在 Swift 4 之前,编译器的版本和语言是一模一样的。但是从 Swift 4 开始,编译器可以在与以前的 Swift 版本兼容的模式下运行。在 Swift 4.0 发行说明中查看有关compatibility modes 的更多信息

Xcode 构建设置SWIFT_VERSION 设置的编译器标志-swift-version 是语言模式。从下面的 swift 编译器打印出来的这个参数只会改变输入的解释方式。

swiftc -h|grep 'Swift language version number'
  -swift-version <vers>   Interpret input according to a specific Swift language version number

因此,当您选择 Swift 语言版本为 4.2 时,这并不意味着使用 Swift 4.2 编译器。编译器版本仍为 5.1.3,Swift 语言版本设置指示编译器以 Swift 4.2 兼容模式运行。兼容模式意味着你可能不需要修改你的 swift 4.2 代码来使用新版本的编译器。因为在兼容模式下运行的编译器允许 Swift 4.2 版代码与 5 版及更高版本的代码一起编译和运行。

具有兼容模式的 Swift 5 编译器可以编译使用 Swift 4 语法Swift 4.2 语法Swift 编写的代码5 语法

这是一个代码示例,使用以下代码创建一个文件 test.swift:

//code written before siwft 5
let firstName = "michael jackson"
let offset = firstName.endIndex.encodedOffset

// Check swift version being used.
#if swift(>=5.2)
print("Hello, Swift 5.2")

#elseif swift(>=5.1)
print("Hello, Swift 5.1")

#elseif swift(>=5.0)
print("Hello, Swift 5.0")

#elseif swift(>=4.2)
print("Hello, Swift 4.2")

#elseif swift(>=4.1)
print("Hello, Swift 4.1")

#elseif swift(>=4.0)
print("Hello, Swift 4.0")

#endif

假设上面的代码是在 swift 5 之前使用 swift 4 编译器编写的 如下所示,此代码将无错误地编译。

在 swift 5 发布后,如果您尝试使用 Swift 5 编译器编译此代码,如下所示。

您将收到上面显示的警告,因为 encodedOffset 在 swift 5 中已被弃用。

您可以降级并使用 swift 4 编译器,也可以在兼容模式下使用 Swift 5 编译器,并带有编译器标志 -swift-version,如下所示。

需要注意的是,Swift 4 编译器Swift-4 兼容模式下的Swift 5 编译器不是一回事。运行兼容模式的 swift 5 编译器通常可以使用新的 swift 5 语言功能。这使得开发人员即使无法升级到 Swift 5 也可以使用新功能。Swift 4 编译器将无法使用新的 Swift 5 功能。

【讨论】:

你的解释对我来说很有意义。仍然没有意义的是如何将 Swift Language Version 设置为 4 或 4.2 不会引发错误,而不是编译 Swift 5 和 5.1 语法。它似乎应该抛出错误。 我已经更新了解释,它是否回答了为什么没有抛出错误。 如果您可以演示一个示例,这将很有帮助。我尝试了一些已弃用的 Swift 4.2 和 Swift 4 功能,并将“Swift 语言版本”设置为支持这些功能的版本并没有消除构建错误和警告。它们的出现与将“Swift Language Version”设置为 Swift 5 时一样。 更新了解释,使用了带有 swift 4 代码的代码示例,同时使用了 swift 4 编译器和 swift 5 编译器。 可能有助于查看github.com/apple/swift-evolution/blob/master/proposals/… 中的表格。区分语言版本和编译器版本。

以上是关于什么是“Swift 语言版本”Xcode 设置?因为它仍然使用旧版本集构建更新的 Swift 代码的主要内容,如果未能解决你的问题,请参考以下文章

对于使用Swift的目标,需要正确配置“Swift语言版本”(SWIFT_VERSION)

使用旧版 Swift 语言版本”(SWIFT_VERSION)不起作用

Xcode 8.0 CBCentralManager 问题

Xcode 8.2使用旧版Swift问题[重复]

带有 xcode 8 的 Alamofire 2.0

Xcode 8.3 不支持 Swift 2.3 [关闭]