为什么我可以将Codable与Swift 3.3的项目语言版本一起使用?

aas*_*gar 2 swift codable

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

Ham*_*ish 6

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

就您而言,听起来您正在使用Swift 4.1编译器,并且“ Swift Language Version”设置为Swift 3.3。这就是所谓的“ Swift 3兼容模式”。请注意,版本Swift 3.3是伪版本–仅存在于代表以Swift 3兼容模式运行的Swift 4.1编译器。

这是一个方便的表格(信息来自SE-0212),该表格将每种兼容模式下的编译器映射到语言版本:

在此处输入图片说明

(请注意,现在已实现SE-0212,对于兼容模式,不再适用于Swift 5及更高版本)

因此,这意味着您正在使用Swift 4.1标准库(包括新Codable协议)并使用Swift 4.1编译器(包括用于Codable综合的必要编译器魔术)进行编译。这就是为什么您仍然可以利用新Codable协议的原因。

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

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

protocol P {}
typealias X = protocol<P, AnyObject>
class C : X {}
Run Code Online (Sandbox Code Playgroud)

但是它不能与以Swift 3兼容模式(SR-8153)运行的Swift 4.1编译器一起编译。

如果DecodableEncodable协议标记为@available(swift, introduced: 4),那么您实际上将无法在Swift 3兼容模式下访问它们。但是没有真正的理由将它们标记为此类,因为没有真正的理由阻止人们在Swift 3模式下利用它们,因为Swift 4编译器完全支持它们。

但是,由于Swift 3兼容性模式仅是–源代码兼容性的临时模式,因此您无法在以后的编译器版本中永久使用它。这将不再是在斯威夫特5编译器选项(你将有斯威夫特4兼容模式,不过)。因此,您需要确保在某个时候将代码库更新到Swift 4,以便能够顺利迁移到Swift 5编译器。

最后,值得注意的是,Swift 4.2中引入了新compiler指令(可以在条件编译块中使用)。与哪个将对照所提供的语言版本进行检查不同,它将根据编译器的实际版本进行检查,而忽略编译器可能在其中运行的任何兼容模式。#if swift(...)-swift-version#if compiler(...)