Swift 5.4发布的新功能介绍

170 阅读5分钟

Swift 5.4现已正式发布! 这个版本包含各种语言和工具的改进。

你可以在Paul Hudson整理的这个游戏场中尝试一些新功能。

语言更新

Swift 5.4包括以下新的语言特性:

  • 支持函数、下标和初始化器中的多个变量参数(SE-0284)
  • 扩展隐含成员语法(SE-0287)
  • 结果构建器(SE-0289)
  • 支持重载的局部函数
  • 局部变量的属性包装器

为了给新的并发模型做准备,编译器现在对不合格的使用await 作为标识符发出警告和修复。 这些标识符将在未来版本的Swift中被解释为关键字await ,作为SE-0296的一部分。

运行时性能和代码大小的改进

在 Swift 5.4 中,运行时的协议一致性检查明显加快,这要归功于用于缓存先前查找结果的更快的哈希表实现。 特别是,这加快了常见的运行时as?as! 铸造操作。

此外,连续的数组修改现在避免了多余的唯一性检查:

func foo(_ a: inout [Int]) {
  // Must do copy-on-write (CoW) check here.
  a[0] = 1
  // The compiler no longer generates
  // a redundant CoW check here.
  a[1] = 2
}

最后,还有各种性能改进:

  • String 插值更积极地被恒定折叠
  • 更少的保留/释放调用,特别是对于inout 函数参数和循环内的调用
  • 标准库中的通用元数据现在在编译时专门化,减少了脏内存的使用并提高了性能

Swift 软件包管理器更新

Swift 包管理器在 Swift 5.4 中有几个重要的更新:

  • 指定 5.4 工具版本的 Swift 包现在可以明确声明目标为可执行,这允许在包代码中使用@main 关键字(SE-0294)
  • Swift Package Manager 现在支持在 Windows 上使用了
  • Swift 软件包管理器以每个用户为单位缓存软件包的依赖关系,这减少了网络流量,并提高了后续使用同一软件包时的依赖关系解决性能。
  • 自动测试发现现在是所有平台上的默认功能,消除了LinuxMain.swift 中的需要(已被废弃)。
  • 对依赖性解析基础设施的多项改进,包括清单加载和缓存,从而提高了依赖性解析的性能。
  • 改进了诊断基础设施和错误信息,使依赖性解决的问题和其他问题有了更多可操作的错误信息。

Windows 平台支持

在 Windows 上对 Swift 的支持在几个重要方面取得了进展:

  • Swift 包管理器现在可以在 Windows 上运行
  • WinSDK 模块已得到扩展,涵盖了 Windows 开发者 SDK 的更大部分。这使得更多的 API 可以轻松地用于 Windows 应用程序,而无需手动构建库来将 C 语言接口连接到 Swift 上。
  • 对安装程序的改进,通过减少Windows上默认所需的标志,使使用工具链的外部工具更加容易。

开发者体验的改进

构建性能

  • Swift 编译器在跟踪文件之间的依赖关系方面做得更好,从而大大减少了增量构建期间许多种类的变化所编译的文件数量。
  • 对结构、枚举、类和协议的成员变量和函数的依赖现在由 Swift 编译器单独跟踪。这种更精细的粒度可以在这些实体发生变化后加快和缩小重建的速度。
  • 增量构建在更多情况下产生确定性的产品。

代码完成

在大型函数体中,代码完成的性能现在要快得多。 在 swift-package-manager 仓库中的一个例子中,Swift 5.4 中self. 的代码完成时间现在比 Swift 5.3 快 4 倍(20ms → 5ms),在该文件中重复调用。

在包含错误的表达式中,以及在没有额外上下文的情况下模糊不清的表达式中,代码完成现在也更加可靠。 例如,鉴于:

func test(a: Int, b: String) -> Int { ... }
func test(a: Int, b: Int) -> String { ... }
func test(a: (Int, Int) -> Int) -> Int { ... }

对于上述代码,代码自动完成现在有如下行为:

  • test().prefix(3). 之后调用代码自动完成,建议成员为String
  • test(a: 2). 后调用代码自动补全,建议使用Int 和 的成员。String
  • 在下面的代码块中,在$0. 之后调用代码自动完成,建议使用Int 的成员。test { $0. }

类型检查器

Swift 5.4 提高了 "链接 "表达式(如a + b + (2 * c) )的类型检查性能。例如,请考虑:

struct S { var s: String? }

func test(_ a: [S]) {
   _ = a.reduce("") {
     ($0 + "," + ($1.s ?? "")) + ($1.s ?? "") + ($1.s ?? "")
   }
}

对于这段代码,类型检查器在100毫秒内完成,而以前它会超时。

此外,对于包含其他字面表达式的嵌套数组字面,类型检查器也提高了性能。 例如,下面这段无效的代码以前会从编译器中产生一个 "太复杂,无法在合理时间内解决 "的信息:

enum E {
  case first
  case second
  case third
}

let dictionary = [
  .first: [0, 1, 2, 3, 4, 5, 6, 7],
  .second: [8, 9, 10, 11, 12, 13, 14, 15],
  .third: [16, 17, 18, 19, 20, 21, 22, 23],
]

现在,Swift 5.4 代码将这段代码诊断为无效,并提供精确的错误信息:

error: reference to member 'first' cannot be resolved without a contextual type
.first : [ 0, 1, 2, 3, 4, 5, 6, 7],
 ^
error: reference to member 'second' cannot be resolved without a contextual type
 .second : [ 8, 9, 10, 11, 12, 13, 14, 15],
 ^
error: reference to member 'third' cannot be resolved without a contextual type
 .third : [16, 17, 18, 19, 20, 21, 22, 23],
 ^

类型检查器现在对结果构建器的诊断有所改进,包括无效的语句(如无效的返回语句)、引用无效的声明和模式匹配错误。比如说:

import SwiftUI

struct ContentView: View {
  @State private var condition = false

  var body: some View {
    Group {
      if condition {
        Text("Hello, World!")
          .frame(width: 300)
      } else {
        return Text("Hello, World!")
      }
    }
  }
}

对于这段代码,类型检查器将报告以下错误,以及一个Fix-It来删除return ,以应用结果构建器:

error: cannot use explicit 'return' statement in the body of result builder 'SceneBuilder'
 return Text("Hello, World!")
 ^