What's new in Swift
Swift & UI 进阶 20m

Swift 5.9 新特性一览

What's new in Swift

2023年6月5日

在 Apple 官方观看视频

一句话判断

Swift 5.9 是近年来最大的一次语言更新——if/else 表达式、参数包、宏系统、ownership 改进和 consume 操作符同时落地,从语法糖到底层内存控制全覆盖。

这场 Session 讲了什么

Ben 和 Doug 联合介绍了 Swift 5.9 的语言特性更新。这场 Session 覆盖面非常广,从社区治理结构变化到具体语法特性都有涉及。

开源社区治理更新:Language Steering Group 在过去一年审核了 40 个语言提案。新引入的 Vision 文档机制用于将多个相关提案整合为一个更大的主题,第一个被接受的 Vision 是 Swift Macros。同时正在组建 Ecosystem Steering Group 来负责工具链、平台支持和文档。

if/else 和 switch 表达式:这可能是最常被请求的语言增强。现在可以在 let 赋值、存储属性初始化等场景中直接用 if/else 和 switch,不再需要丑陋的三元表达式嵌套或立即执行的闭包 hack。

参数包(Parameter Packs):终结了”为每个参数数量写一遍重载”的模式。现在可以写一个泛型函数处理任意数量的类型参数,同时保留每个参数的静态类型信息。

Swift Macros:这是今年最重磅的新特性。宏允许在编译期生成代码,减少样板代码,同时保持类型安全。Session 展示了宏如何简化 Codable、Equatable 等协议的实现。

Ownership 和 consume 操作符:为底层性能代码提供了更精细的内存控制。consume 操作符允许显式结束变量的生命周期,编译器可以据此优化内存管理。

Result Builder 改进:类型检查性能优化,错误信息更精确。之前无效代码会导致误导性的错误提示,现在能准确指向问题所在。

值得深挖的点

if/else 表达式的适用范围:不仅限于局部变量赋值,全局变量和存储属性的初始化也能用。这意味着 SwiftUI 中很多 View 的条件构建可以用更自然的方式写。

宏的两层架构:Attached Macros(附加宏)和 Freestanding Macros(独立宏)。附加宏用 @ 前缀,作用于声明上(如 @Observable);独立宏用 # 前缀,直接生成表达式或声明(如 #unwrap)。宏在编译时展开为合法的 Swift 代码,可以在 Xcode 中右键宏展开查看生成的内容。

consume 的性能含义:Swift 的 copy-on-write 机制已经很高效,但在某些场景(大数组传递、低级系统编程)下,显式 consume 能让编译器更好地优化。consume 后的变量不能再被使用,编译器会在编译期检查这一点。

值和引用类型的统一 consume 语义:consume 不仅适用于值类型(让编译器避免不必要的拷贝),也适用于引用类型(配合 weak 引用实现更明确的生命周期管理)。

代码片段

// if/else 表达式 - 告别丑陋的三元运算符嵌套
let textColor = if darkMode {
    Color.white
} else {
    Color.black
}

// 存储属性初始化 - 不再需要立即执行闭包
let defaultConfiguration: Config = switch environment {
    case .production: Config(secure: true, timeout: 30)
    case .staging:    Config(secure: true, timeout: 60)
    case .debug:      Config(secure: false, timeout: 120)
}
// 参数包 - 一个函数替代所有重载
func evaluate<each Result>(
    _ request: repeat Request<each Result>
) -> (repeat each Result) {
    return (repeat evaluate(each request))
}

// 调用方式完全自然,类型自动推导
let single = evaluate(boolRequest)       // 返回 Bool
let triple = evaluate(r1, r2, r3)        // 返回 (T1, T2, T3)
// Swift Macros - 减少样板代码
@Observable  // 附加宏,自动生成观察机制
class ViewModel {
    var items: [Item] = []
    var isLoading = false
}

// 独立宏,编译期代码生成
#unwrap(optionalValue) { value in
    // 这里 value 已经解包,不需要 if let
    process(value)
}
// consume 操作符 - 显式结束变量生命周期
func processLargeData(_ data: consuming [Int]) {
    // data 的所有权在进入函数时转移
    // 不需要额外的拷贝
    for item in data {
        handle(item)
    }
    // data 在函数结束时被销毁
}

// 显式 consume
var buffer = loadData()
processLargeData(consume buffer)
// buffer 在此处之后不能再使用

最佳实践

  • 用 if/else 表达式替代三元运算符:当条件逻辑超过一层时,if/else 表达式比嵌套三元运算符可读性好得多。
  • 在库 API 中考虑参数包:如果你的 API 有多个仅参数数量不同的重载,参数包能大幅减少代码量并消除人为的参数上限。
  • 用 Xcode 的宏展开功能调试宏:右键点击宏,选择”Expand Macro”查看生成的内容。理解宏生成了什么代码是正确使用宏的前提。
  • 只在性能敏感路径使用 consume:日常 Swift 代码不需要关心 consume。只在处理大数据结构或写底层系统代码时才需要用它做显式优化。
  • 关注 Result Builder 错误信息的改善:如果你在写 SwiftUI 代码时经常遇到令人困惑的编译错误,Swift 5.9 的错误信息应该会好很多。

还有什么值得关注

  • Swift 社区的治理结构正在完善——Language Steering Group 管语言演进,新的 Ecosystem Steering Group 管工具和生态。这对 Swift 的长期健康发展很重要。
  • Vision 文档机制意味着未来会有更多大规模的语言变更以统一规划的方式推进,而不是零散的提案。
  • Session 强调 Swift 的设计哲学是”渐进式披露”——初学者不需要理解宏和参数包就能写出好用的代码,这些高级特性只在写库和框架时才需要。
  • Ownership 模型是 Swift 未来发展的方向之一,consume 是这个方向的第一个里程碑。未来可能会有更多所有权相关的特性。
  • Swift 5.9 的更新密度说明 Swift 语言正在快速成熟,每年都有实质性的能力提升而不是小修小补。
WWDC 2023