为什么我可以在Swift 3.3的项目语言版本中使用Codable?

为什么我可以在Swift 3.3的项目语言版本中使用Codable?,swift,codable,Swift,Codable,Codable在Swift 4中得到介绍。我的项目语言版本是Swift 3.3,但我仍然能够在我的项目中使用Codable。这不是问题,但怎么可能呢?我只是想知道。我想您可能正在使用最新的Swift编译器。Swift编译器版本和“Swift语言版本”构建设置(对应于-Swift version命令行标志)是两件不同的事情。前者是您正在使用的编译器和标准库的实际版本,而后者只是一个标志,告诉编译器尝试模仿以前Swift版本的行为。这允许更平滑的迁移体验–您可以更新到最新的Swift编译器,而无需立

Codable在Swift 4中得到介绍。我的项目语言版本是Swift 3.3,但我仍然能够在我的项目中使用Codable。这不是问题,但怎么可能呢?我只是想知道。

我想您可能正在使用最新的Swift编译器。

Swift编译器版本和“Swift语言版本”构建设置(对应于
-Swift version
命令行标志)是两件不同的事情。前者是您正在使用的编译器和标准库的实际版本,而后者只是一个标志,告诉编译器尝试模仿以前Swift版本的行为。这允许更平滑的迁移体验–您可以更新到最新的Swift编译器,而无需立即更新代码库以适应语言中的最新更改

在您的例子中,听起来您使用的是Swift 4.1编译器,“Swift语言版本”设置为Swift 3.3。这被称为“Swift 3兼容模式”。请注意,Swift 3.3版本是一个伪版本–它的存在仅代表在Swift 3兼容模式下运行的Swift 4.1编译器

下面是一个方便的表(信息取自),它将编译器映射到每个兼容模式的语言版本:

(请注意,现在已实施,对于Swift 5和更高版本,将不再发生兼容模式的此版本碰撞)

这意味着您正在使用Swift 4.1标准库(其中包括新的
Codable
协议)并使用Swift 4.1编译器进行编译(其中包括
Codable
合成所需的编译器魔法)。这就是为什么您仍然能够利用新的
Codable
协议的原因

但是,通过在Swift 3兼容模式下运行,可以指示编译器模仿Swift 3编译器的行为。例如,这将导致它允许您访问标记为
@available(swift,废弃:4)
的声明,阻止您访问标记为
@available(swift,引入:4)
的声明,忽略
中的代码,如果swift(>=4)
条件编译块,并且尽最大努力保持与Swift 3的源代码兼容性

后者并不总是完美实现,例如,它使用Swift 3.1编译器编译:

protocol P {}
typealias X = protocol<P, AnyObject>
class C : X {}
协议P{}
typealias X=协议
C类:X{}
但它不是使用在Swift 3兼容模式()下运行的Swift 4.1编译器编译的

如果
Decodable
Encodable
协议被标记为
@可用(swift,介绍:4)
,那么您确实无法在swift 3兼容模式下访问它们。但是没有真正的理由将它们标记为这样,因为没有真正的理由阻止人们在Swift 3模式下利用它们,因为Swift 4编译器完全支持它们

然而,因为Swift 3兼容模式只是一种源代码兼容的临时模式,所以您不能在将来的编译器版本中永远使用它。它(不过,您将拥有Swift 4的兼容模式)。因此,您需要确保在某个时候将代码库更新到Swift 4,以便能够顺利迁移到Swift 5编译器

最后,值得注意的是一个新的
编译器
指令(可以在条件编译块中使用)。与根据
-swift version
提供的语言版本进行检查的
\if-swift(…)
不同,
\if-compiler(…)
将根据编译器的实际版本进行检查,忽略它可能运行的任何兼容模式