为什么我可以将 Codable 与 Swift 3.3 的项目语言版本一起使用?
Why can I use Codable with a project language version of Swift 3.3?
Codable 在 Swift 4 中被引入。我的项目语言版本是 Swift 3.3,但我仍然可以在我的项目中使用 Codable。这不是问题,但这怎么可能呢?我只想知道。
我想你可能使用的是最新的 Swift 编译器。
Swift 编译器版本和"Swift Language Version" 构建设置(对应于
-swift-version
命令行标志)是两个不同的东西。前者是您正在使用的 实际 版本的编译器和标准库,而后者只是一个标志,告诉编译器尝试模仿之前 Swift 的行为版本。这允许更流畅的迁移体验——您可以更新到最新的 Swift 编译器,而无需立即更新您的代码库以适应语言的最新变化。
在您的情况下,听起来您使用的是 Swift 4.1 编译器,"Swift Language Version" 设置为 Swift 3.3。这被称为 "Swift 3 compatibility mode"。请注意,版本 Swift 3.3 是伪版本 - 它的存在仅代表 Swift 4.1 编译器 运行 在 Swift 3 兼容模式下。
这是一个方便的 table(信息取自 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 {}
但它无法在 Swift 3 兼容模式 (SR-8153) 中使用 Swift 4.1 编译器 运行 进行编译。
如果 Decodable
和 Encodable
协议被标记为 @available(swift, introduced: 4)
,那么您确实无法在 Swift 3 兼容模式下访问它们。但是没有真正的理由这样标记它们,因为没有真正的理由阻止人们在 Swift 3 模式下利用它们,因为 Swift 4 编译器完全支持它们。
然而,由于 Swift3 兼容模式只是一种源代码兼容性的临时模式,因此您无法在未来的编译器版本中永远使用它。它 will no longer be an option in the Swift 5 compiler(但是,您将拥有 Swift 4 的兼容模式)。因此,您需要确保在某个时候将代码库更新为 Swift 4,以便能够顺利迁移到 Swift 5 编译器。
最后,值得注意的是新的 compiler
指令(可用于条件编译块)is being introduced in Swift 4.2。与 #if swift(...)
检查由 -swift-version
提供的语言版本不同,#if compiler(...)
将检查编译器的实际版本,忽略它可能在 运行 中的任何兼容模式。
Codable 在 Swift 4 中被引入。我的项目语言版本是 Swift 3.3,但我仍然可以在我的项目中使用 Codable。这不是问题,但这怎么可能呢?我只想知道。
我想你可能使用的是最新的 Swift 编译器。
Swift 编译器版本和"Swift Language Version" 构建设置(对应于
-swift-version
命令行标志)是两个不同的东西。前者是您正在使用的 实际 版本的编译器和标准库,而后者只是一个标志,告诉编译器尝试模仿之前 Swift 的行为版本。这允许更流畅的迁移体验——您可以更新到最新的 Swift 编译器,而无需立即更新您的代码库以适应语言的最新变化。
在您的情况下,听起来您使用的是 Swift 4.1 编译器,"Swift Language Version" 设置为 Swift 3.3。这被称为 "Swift 3 compatibility mode"。请注意,版本 Swift 3.3 是伪版本 - 它的存在仅代表 Swift 4.1 编译器 运行 在 Swift 3 兼容模式下。
这是一个方便的 table(信息取自 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 {}
但它无法在 Swift 3 兼容模式 (SR-8153) 中使用 Swift 4.1 编译器 运行 进行编译。
如果 Decodable
和 Encodable
协议被标记为 @available(swift, introduced: 4)
,那么您确实无法在 Swift 3 兼容模式下访问它们。但是没有真正的理由这样标记它们,因为没有真正的理由阻止人们在 Swift 3 模式下利用它们,因为 Swift 4 编译器完全支持它们。
然而,由于 Swift3 兼容模式只是一种源代码兼容性的临时模式,因此您无法在未来的编译器版本中永远使用它。它 will no longer be an option in the Swift 5 compiler(但是,您将拥有 Swift 4 的兼容模式)。因此,您需要确保在某个时候将代码库更新为 Swift 4,以便能够顺利迁移到 Swift 5 编译器。
最后,值得注意的是新的 compiler
指令(可用于条件编译块)is being introduced in Swift 4.2。与 #if swift(...)
检查由 -swift-version
提供的语言版本不同,#if compiler(...)
将检查编译器的实际版本,忽略它可能在 运行 中的任何兼容模式。