嵌入式 Swift 的改进即将在 Swift 6.4 中推出

嵌入式Swift 是 Swift 的一个子集,专为低资源占用而设计,使其能够在微控制器等受限环境中运行。通过使用特殊的编译模式,Embedded Swift 生成的二进制文件比普通 Swift 小得多。

尽管只是完整语言的一个子集,但绝大多数 Swift 语法在 Embedded Swift 中仍能完全照常使用。更多信息请参阅 嵌入式Swift愿景文档

Embedded Swift 正在快速演进。继去年年底发布的 Swift 6.3 中的嵌入式 Swift 改进 更新之后,本文将介绍即将推出的 Swift 6.4 版本中新增的多项改进。

您现在就可以通过 Swift 开发快照 试用这些功能。

语言层面的改进

Embedded Swift 不断扩展其语言子集,纳入更多“完整”Swift 的特性,从而让现有 Swift 代码库更容易与 Embedded Swift 兼容。其中许多特性带有一定的动态性,这意味着它们会对运行时性能(例如因间接调用)和代码大小(因需要额外的元数据)产生影响。

不过,这种影响仅在实际使用这些动态语言特性时才会出现:对代码大小和性能极为敏感的代码可以主动避开它们,比如在 PerformanceHints 诊断组 中启用相关警告。

泛化支持存在类型(any

此前,Embedded Swift 仅支持带有 AnyObject 约束的存在类型(any),即只能用于类实例。如今,所有 any 类型在 Embedded Swift 中均已可用,包括 Any 本身。

例如:

protocol P {
  func method()
}

extension Int: P {
  func method() { print("\(self) is here") }
}

let a: any P = 17
a.method() // 输出 “17 is here”

Embedded Swift 的泛型编译模型要求所有泛型函数和类型最终都必须进行特化,这给 any 类型的使用带来了一些限制。具体而言,泛型函数无法直接作用于 any 类型:

extension P {
  func genericMethod(_ other: T) { ... }
}

let a: any P = 17
a.genericMethod(a) // 错误:在 Embedded Swift 中,不能对 ‘any P’ 类型的值调用泛型实例方法 ‘genericMethod’

未指定类型的抛出

此前,Embedded Swift 仅允许抛出特定的错误类型,例如:

func parseRecord() throws(ParsingError) -> Record { ... }

而“未指定类型”的抛出——即可以抛出任何符合 Error 协议的实例——在 Embedded Swift 中是被禁止的:

func loadImage() throws -> Image { ... } // 此前在 Embedded Swift 中被禁止

未指定类型的抛出等价于抛出一个 any Error 类型的值。随着 any 类型的泛化,Embedded Swift 现已全面支持未指定类型的抛出。由于抛出 any Error 通常需要堆分配,因此对于希望避免堆分配的代码库,仍应优先选择指定类型的抛出。

元类型

传统上,Embedded Swift 仅在极少数场景下允许使用元类型(如 Int.self),例如在为泛型函数指定参数类型时:

rawPointer.bindMemory(to: Value.self, capacity: 1)

Swift 6.4 在 Embedded Swift 中实现了对元类型的全面支持:用户可以创建并使用元类型的实例,包括存在类型,如 any (DefaultInitializable.Type)

例如,以下用法现已获准,并且行为与完整版 Swift 完全一致:

protocol DefaultInitializable {
  init()
}

extension Int: DefaultInitializable { }

let factory: any (DefaultInitializable.Type) = Int.self
let aValue: any DefaultInitializable = factory.init()

标准库的改进

来自完整版 Swift 的标准库及配套库中的更多功能,现已在 Embedded Swift 中可用。

浮点数解析

Swift 中的浮点数值可以从字符串中解析,例如:

let inputText: String = getInputText()
if let value = Double(inputText) {
  // value 是一个 Double
}

作为 在 Swift 中重新实现此功能 的一部分,这些浮点数解析 API 现在也已在 Embedded Swift 中提供。

并发错误处理

Embedded Swift 的并发库 now 支持抛出操作,例如抛出的任务和任务组。例如:

let task = Task {
  if badThing {
    throw MyError.badThingHappened
  }

  return "ok"
}

print(try await task.value)

立即体验!

Embedded Swift 的支持已在 快速开发快照 中提供。入门的最佳方式是参考 Swift 嵌入式示例 仓库中的示例,其中包含多个样例项目,帮助您在各类硬件上构建并运行 Embedded Swift 代码。

如果您对本文所述的改进有任何疑问,或希望交流您自己的 Embedded Swift 开发经验,欢迎加入 Swift 论坛的讨论。您可以在 关联线程 中针对本文提问,并在 嵌入式Swift类别 中分享您的实践心得。

添加评论
点赞收藏
点踩分享查看原文
评论
?
参与讨论