一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第21天,点击查看活动详情。
一、Enum
枚举的基本用法
Swift语言中使用**enum**关键字来进行枚举的创建。
///创建一个姓氏枚举类型
enum Surname {
case 赵
case 钱
case 孙
case 李
}
上面的代码创建了一个姓氏枚举类型,这个枚举类型中定义了4个枚举值,分别是赵、钱、孙、李,上面的写法将4个枚举值分别在4个case语句中定义,开发者也可以在1个case子句中完成多个枚举值的定义,如
///创建一个姓氏枚举类型
enum Surname {
case 赵, 钱,孙,李
}
枚举的原始值和相关值
枚举的原始值特性可以将枚举值与另一种数据类型进行绑定,相关值则可以为枚举值关联一些其他数据。通过相关值,开发者可以实现复杂的枚举类型。
枚举的原始值
swift语言中的枚举支持开发者声明一个原始值类型,并将某个已经存在的类型的值与枚举值进行绑定,枚举指定原始值类型的语法与继承的语法有些类似,示例代码如下:
///为枚举类型指定一个原始值类型
enum CharEnum: Character {
///通过赋值的方式为枚举值设置一个原始值
case a = "a"
case b = "b"
case c = "c"
case d = "d"
}
如果开发者要指定枚举的原始值类型为Int类型,那么可以只设置第一个枚举值的原始值,其后的枚举值的原始值会在第一个枚举值原始值的基础上依次递增,示例如下:
enum IntEnum: Int {
///第一个枚举值的原始值设置为1
case a = 1
///默认原始值为2
case b
///默认原始值为3
case c
///默认原始值为4
case d
}
通过枚举类型中的**rawValue**属性来获取枚举的原始值,示例如下:
enum CharEnum: Character {
///通过赋值的方式为枚举值设置一个原始值
case a = "a"
case b = "b"
case c = "c"
case d = "d"
}
var char = CharEnum.a
var value = char.rawValue
print(value)
隐式RawValue分配是建立在swift的类型推断机制上的。
enum DayOfWeek: String {
case mon, tue, wed, thu, fri = "Hello World", sat, sun
}
print(DayOfWeek.mon.rawValue)
print(DayOfWeek.fri.rawValue)
print(DayOfWeek.sat.rawValue)
lldb打印输出
mon
Hello World
sat
我们当前的系统已经默认给我们的每一个枚举值分配了一个字符串,而这个字符串其实跟我们枚举成员值的字符串是一致的。那么它到底是怎么做到的哪,我们在SIL文件看一下。
enum DayOfWeek : String {
case mon, tue, wed, thu, fri, sat, sun
init?(rawValue: String)
typealias RawValue = String
var rawValue: String { get }
}
// main
sil @main : $@convention(c) (Int32, UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>) -> Int32 {
bb0(%0 : $Int32, %1 : $UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>):
alloc_global @$s4main1xSSvp // id: %2
%3 = global_addr @$s4main1xSSvp : $*String // user: %8
%4 = metatype $@thin DayOfWeek.Type
%5 = enum $DayOfWeek, #DayOfWeek.mon!enumelt // user: %7
// function_ref DayOfWeek.rawValue.getter
%6 = function_ref @$s4main9DayOfWeekO8rawValueSSvg : $@convention(method) (DayOfWeek) -> @owned String // user: %7
%7 = apply %6(%5) : $@convention(method) (DayOfWeek) -> @owned String // user: %8
store %7 to %3 : $*String // id: %8
%9 = integer_literal $Builtin.Int32, 0 // user: %10
%10 = struct $Int32 (%9 : $Builtin.Int32) // user: %11
return %10 : $Int32 // id: %11
}
这里就是在访问我们rawValue的getter方法。
sil hidden @$s4main9DayOfWeekO8rawValueSSvg : $@convention(method) (DayOfWeek) -> @owned String {
// %0 "self" // users: %2, %1
bb0(%0 : $DayOfWeek):
debug_value %0 : $DayOfWeek, let, name "self", argno 1 // id: %1
switch_enum %0 : $DayOfWeek, case #DayOfWeek.mon!enumelt: bb1, case #DayOfWeek.tue!enumelt: bb2, case #DayOfWeek.wed!enumelt: bb3, case #DayOfWeek.thu!enumelt: bb4, case #DayOfWeek.fri!enumelt: bb5, case #DayOfWeek.sat!enumelt: bb6, case #DayOfWeek.sun!enumelt: bb7 // id: %2
switch_enum %0 就是我们传进来的当前枚举成员值mon,接下来就是一个模式匹配,匹配我们当前的成员值。匹配上了**swift case #DayOfWeek.mon!enumelt: bb1**代码块。
bb1: // Preds: bb0
%3 = string_literal utf8 "mon" // user: %8
那么这个字符串 "mon" 是从哪里得到的哪?这样的字符串其实就是一个字符串常量,而字符串常量存储在哪里哪,我们把Mach-o文件拖到MachoView应用来查看一下。