Swift language announcements from WWDC22
在过去的一年里,Swift 有了显着的发展,我们已经看到了该语言的两次大更新。Swift 5.6 于 2022 年 3 月发布,对类型系统、并发模型和 Swift 生态系统进行了重大改进。它为 Swift 5.7 的进一步更新奠定了基础,该版本包含在 Xcode 14 的 beta 版本中,可在 Swift.org 下载页面上找到。
在 WWDC22 期间,许多 Swift 更新得到了适当的讲解,session 重点关注语言更改、工具改进、Swift 包的添加等等。What's new in Swift 视频很好地概述了过去一年的 Swift 新闻。在这篇文章中,我们想分享来自 WWDC 的关于 Swift 生态系统的亮点。
社区发展
围绕 Swift 语言的社区正在发展壮大,之前介绍的一些举措正在扩大并获得更广泛的支持。已宣布新的工作组将专注于 Swift 生态系统中的特定领域。Swift 网站工作组正在指导 Swift.org 网站的发展,Swift 和 C++ 互操作性小组正在致力于推进两种语言之间的互操作性支持,而 Swift 语言工作组正在监督语言和标准库。2021 年宣布的 Swift Mentorship Program 已延长一年,并包括其他主题,例如 DocC、C++ 互操作性和 Swift 网站。值得一提的是,Swift.org 网站现已开源,并准备好接受社区贡献。
说到开源,去年宣布的 Swift 框架和包的 Swift-DocC 编译器现在也开源了,并且有了一些很大的改进。它增加了对应用程序项目的支持以及对 Objective-C 和 C API 文档的支持。我们绝对建议您查看 Swift-DocC session 中的新增功能以了解更多信息。
Swift Packages
我们已经看到 Swift 包管理器的重要更新,包括对模块消歧的支持、定义构建工具插件和自定义命令插件的能力,以及安全性和性能改进。
从 Swift 5.6 开始,Swift Package Manager 执行首次使用时的信任 (TOFU) 验证。首次下载包时会记录包的指纹,如果指纹不同,后续下载会报错。此更改对于更好的包安全性非常有用。
在 Swift 5.7 中,Swift 包管理器获得了令人兴奋的改进,这将帮助我们避免在项目中使用多个同名包时出现问题。它现在允许我们从定义它们的包之外命名模块,并添加模块别名。
使用新的 PackagePlugin API,我们可以定义自定义插件来生成源代码或自动化发布任务。Create Swift Package plugins 课程教我们如何在 Swift 中编写这样的插件。
语言更新
今年,我们看到了 Swift 语言的一些重要补充,其中包括一系列变化,从较小的语法改进到较大的泛型和并发更新。
这篇文章重点介绍了在 WWDC 上引起我们注意的一些 Swift 更新。对于以下部分中的代码示例,我们从新西兰 Aotearoa 的年度鸟类竞赛中获得灵感。毕竟,考虑到谁是 2021 年年度鸟类的获胜者(这是一只蝙蝠🤫),对参赛者来说一些额外的类型安全不会受到伤害。
生活质量改善
Swift 5.7 中一个很小但非常好的改进是使用 if let、guard let 和 while let 进行可选解包的简写语法。我们可以删除右侧以获取与原始名称相同的未包装选项。
var startDate: Date?if let startDate { print("""
Bird of the Year competition \
starts on \(startDate.formatted())
""")
}
另一个将改进我们的代码的更改是对具有多个语句的复杂闭包的类型推断支持。如果我们的闭包包含 if else、do catch 或任何其他控制流语句,我们不再需要手动指定返回类型。
let participants = ["Kororā", "Weka", "Pekapeka-tou-roa"]let introductions = participants.map { if $0.hasPrefix("Pekapeka") { return "\($0) is a mammal"
} else { return "\($0) is a bird"
}
}
字符串处理
Swift 5.7 对字符串处理进行了重大更新,引入了正则表达式文字和 RegexBuilder 库,并与匹配方法和强类型捕获配对。
我们可以命名我们的匹配项并轻松地从最终结果中提取它们。
let intent = "I vote for Pūkeko and Kea"let regex = /I vote for (?<bird1>.+?) and (?<bird2>.+?)/if let votes = try? regex.wholeMatch(in: intent) { print("Your first choice is \(votes.bird1)") print("Your second choice is \(votes.bird2)")
}
使用 RegexBuilder,我们可以使用 SwiftUI 风格的语言构建我们的正则表达式搜索,这可以使其更具可读性并解锁更强大的功能。
let word = OneOrMore(.word)let regex = Regex { "I vote for "
Capture { word } " and "
Capture { word }
}if let votes = try? regex.wholeMatch(in: intent) { let (_, bird1, bird2) = votes.output print("Your first choice is \(bird1)") print("Your second choice is \(bird2)")
}
有两个关于新字符串处理 API 的信息丰富的 session:Meet Swift Regex 和 Swift Regex: Beyond the basics。
泛型和协议
今年对 Swift 协议和泛型有很多改进。协议现在支持主要关联类型。我们可以在协议名称旁边的尖括号中指定它,它应该是调用现场比其他人更频繁使用的类型。
protocol Contestant<Habitat> {
associatedtype Habitat: Territory
associatedtype Food
var home: Habitat { get set } var favoriteFood: Food { get set } var name: String { get }
}
使用尖括号语法,我们可以将主要关联类型约束为特定类型。
func fundReforestation<Animal: Contestant<Forest>>(for animal: Animal) {
scheduleTreePlanting(in: animal.home)
}
由于使用一些参数类型的新能力,编写泛型方法和函数也变得更容易。如果泛型参数只用在一个地方,我们可以指定协议和一些关键字来表示它的类型,而不需要对函数设置泛型约束。
func fundConservationEfforts(for animal: some Contestant) {
establishProtectedAreas(in: animal.home)
startIntensiveMonitoring(of: animal)
}
我们甚至可以使用一些具有主要关联类型约束的参数,因此我们可以以更简洁的方式重写我们前面的fundReforestation() 函数示例。
func fundReforestation(for animal: some Contestant<Forest>) {
scheduleTreePlanting(in: animal.home)
}
Swift 中的存在类型也有大量改进。我们现在可以使用 any 关键字来标记使用存在类型的位置,并且我们不再有以前使用具有 Self 或关联类型要求的存在类型的约束。我们可以将它们放入集合中,使用存在类型来约束变量或将其用作参数类型。
例如,我们可以创建一个参赛者数组,这是我们以前无法做到的,因为我们示例中的参赛者协议具有关联的类型。
let contestants: [any Contestant] = [
brownKiwi, ruru, whio
]for contestant in contestants {
fundConservationEfforts(for: contestant)
}
知道之前存在类型的约束已经消失,我们可以审核我们现有的类型擦除包装器的代码,并检查我们现在是否可以使用存在类型重新实现它们。
要了解有关 Swift 5.7 中泛型的更多信息,请务必查看 Embrace Swift generics 这个 session。要了解如何使用协议设计高级抽象,请观看在 Design protocol interfaces in Swift。
并发
今年的并发更新建立在去年的变化之上,并专注于数据竞赛安全。我们甚至在 Xcode 中加入了新的可选安全检查,以帮助我们识别潜在问题。
去年推出的 Swift Actor 通过隔离对其属性的访问来帮助我们编写线程安全的代码。今年新的分布式参与者进一步采用了参与者隔离的概念,并使开发分布式系统变得更加简单。开源分布式 Actors 库为在 Swift 中构建服务器端集群分布式系统提供了完整的解决方案。Meet distributed actors in Swift 视频更详细地介绍了在使用分布式系统和应用程序时使用 actor。
我们还有一个新的 Swift 包 Async Algorithms,它为使用 AsyncSequence 提供了现成的解决方案。它包括我们自己可能难以实现的算法,例如去抖动、节流、合并和压缩。这些算法帮助我们随着时间的推移处理值。
let kiwiFinder = KiwiFinder()let counter = Counter()for try await (i, kiwi) in zip(counter, kiwiFinder) { print("Kiwi number \(i) is a \(kiwi.name)")
}
Swift 的另一个重要补充是与时间交互的新标准方式,它包括三个不同的组件:时钟、瞬间和持续时间。这些新的 API 与并发任务很好地集成在一起。
func announceWinner(_ winner: some Contestant) async throws { print("Building suspense...") try await Task.sleep(
until: .now + .seconds(10),
tolerance: .seconds(1),
clock: .suspending
) print("The winner is \(winner.name)!")
}
要了解有关 Async Algorithms 包的更多信息并发现使用 Swift Clock 类型随时间处理值的最佳实践,请查看 Meet Swift Async Algorithms WWDC session。
Swift 中的并发支持在今年获得了许多其他重大升级,例如针对提高性能的优化、actor 优先级和内置的优先级反转避免。Instruments 现在有一个新的 Swift 并发模板,可以帮助我们调查性能问题。可视化和优化 Swift 并发讨论讨论了我们在应用程序中可能遇到的常见问题,并展示了如何使用 Instruments 来查找和解决性能问题。
还有很多很棒的更新,不可能全部覆盖。由于并行化、使用协议和 where 子句对函数签名进行更快的类型检查、运行时协议一致性检查的优化等,我们在 Xcode 中的构建速度越来越快。通过减少标准库的大小,Swift 可以在各种环境中运行,并且通过简化的 Linux 工具链分发,我们中的更多人可以在我们最喜欢的平台上享受使用 Swift 的乐趣。
我们非常期待进一步探索所有这些新功能并在我们的项目中使用它们。