返回

Swift 中的神秘枚举

IOS

序幕

枚举是 Swift 中一种非常强大的类型,它可以用来表示一组相关的常量。枚举的成员可以是显式定义的,也可以是隐式分配的。枚举还可以有 RawValue,这是一种可以在枚举成员中存储的原始值。

枚举的种类

隐式分配机制

隐式分配机制是指,当我们没有显式地为枚举成员指定值时,编译器会自动为它们分配值。这种分配机制从 0 开始,并且对于每个后续的枚举成员,其值都会增加 1。例如:

enum CompassPoint {
    case north
    case south
    case east
    case west
}

在这个枚举中,north 的值是 0,south 的值是 1,east 的值是 2,west 的值是 3。

RawValue

RawValue 是可以在枚举成员中存储的原始值。RawValue 可以是任何类型,但最常见的是整数、字符串或布尔值。例如:

enum Planet: Int {
    case mercury = 1
    case venus = 2
    case earth = 3
    case mars = 4
}

在这个枚举中,mercury 的 RawValue 是 1,venus 的 RawValue 是 2,earth 的 RawValue 是 3,mars 的 RawValue 是 4。

枚举在 SIL 文件中的表示

在 SIL 文件中,枚举的 getter 方法是用来获取枚举值的。例如,对于以下枚举:

enum CompassPoint {
    case north
    case south
    case east
    case west
}

其 getter 方法的 SIL 表示如下:

sil hidden [transparent] @$s12CompassPointO5northACvg : $@convention(thin) (@guaranteed CompassPoint) -> Int {
bb0(%0 : $*CompassPoint):
  %1 = integer_literal $Builtin.Int64, 0
  switch_enum %0 : $CompassPoint, case #CompassPoint.north!enumelt: bb1, case #CompassPoint.south!enumelt: bb2, case #CompassPoint.east!enumelt: bb3, case #CompassPoint.west!enumelt: bb4
bb1:
  br bb5(%1 : $Builtin.Int64)
bb2:
  %2 = integer_literal $Builtin.Int64, 1
  br bb5(%2 : $Builtin.Int64)
bb3:
  %3 = integer_literal $Builtin.Int64, 2
  br bb5(%3 : $Builtin.Int64)
bb4:
  %4 = integer_literal $Builtin.Int64, 3
  br bb5(%4 : $Builtin.Int64)
bb5(%5 : $Builtin.Int64):
  return %5 : $Builtin.Int64
}

在这个 SIL 代码中,switch_enum 指令用于根据枚举值的类型来跳转到不同的基本块。例如,如果枚举值是 north,则会跳转到 bb1 基本块。在 bb1 基本块中,integer_literal 指令用于创建一个整数字面量 0,然后 br 指令用于返回这个整数字面量。

枚举值的字符串表示

枚举值的字符串表示是在编译的时候就已经构建好的,并且存放在 Macho 文件中。例如,对于以下枚举:

enum CompassPoint {
    case north
    case south
    case east
    case west
}

其枚举值的字符串表示如下:

CompassPoint.north = "north"
CompassPoint.south = "south"
CompassPoint.east = "east"
CompassPoint.west = "west"

这些字符串表示存放在 Macho 文件的字符串表中。当我们使用 String(describing:) 函数来获取枚举值的字符串表示时,编译器会从字符串表中查找相应的字符串。

结语

枚举是 Swift 中一种非常强大的类型,它可以用来表示一组相关的常量。枚举可以有隐式分配机制,也可以有 RawValue。在 SIL 文件中,枚举的 getter 方法是用来获取枚举值的。构建枚举值的字符串是在编译的时候就已经构建好的,并且存放在 Macho 文件中。