Swift(十九)-枚举及其原始值

「这是我参与2022首次更文挑战的第27天,活动详情查看:2022首次更文挑战

枚举类型的创建

Swift语言中,通过enum关键字来进行枚举的创建,比如,我们可以创建一个花的枚举类型:

image.png

我们使用case进行枚举类型的定义,在上述代码中,我们每一个定义都使用了一个case,我们也可以在一个case中定义多个枚举值:

image.png

枚举值的使用

在使用时,和其他类型一样,我们可以在声明变量时将其类型指定为某个枚举类型,或者通过变量初始化的方式让编译器自动推断出变量的类型。

Swift中,如果已经确认变量是某一个枚举类型,那么在使用时,可以将枚举类型省略掉,直接使用点语法,如下:

image.png

我们通过两种方式定义了f1f2两个变量,他们都是Flowers的枚举类型,不同的是f1是先声明变量,然后进行赋值,而f2是直接给变量一个初始化的值,让编译器自动判断其类型,然后进行再次赋值;

需要注意的是,因为f2在进行初始化时,必须告诉编译器他是哪一个枚举类型,所以不能省略枚举类型:

image.png

在实际开发中,枚举类型经常与switch-case结合使用来实现选择,如下:

image.png

需要注意的是,在switch需要穷尽枚举值,否则将会报错;

枚举的原始值

枚举原始值特性可以将枚举值与另一个数据类型进行绑定,相关值则可以为枚举值关联一些其他数据;

原始值

COC中,枚举时默认受整数支持的,也就意味着在如下枚举中,A,B,C分别默认为0,1,2

image.png

Swift中的枚举则更加灵活,并且不需要给枚举中的每一个成员都提供值,如果一个值原始值要被提供给每一个枚举成员,那么这个值可以是字符串字符或者浮点类型等等;

如下,我们给枚举指定一个原始值类型:

image.png

我们给Flowers指定为String类型,并通过赋值的方式来为枚举值设置一个原始值

如果我们要指定的枚举的原始值类型Int类型,那么可以只设置第一个枚举值的原始值,其后边的的枚举值的原始值会在第一个枚举值原始值的基础上记性依次递增,这属于隐式RawValue分配,其建立在Swift的类型推断机制上,如下代码:

image.png

我们可以通过枚举类型中的rawValue属性来获取枚举的原始值,我们看如下代码:

image.png

通过rawValue属性我们获取到了枚举的原始值,我们还发现,对于String类型的枚举而言,系统给每一个枚举都默认了一个同名的原始值;我们可以通过SIL文件来分析一下:

image.png

我们在访问rawValue的时候,其实是在访问其get方法,我们通过下边代码来分析一下其过程:

image.png

生成SIL文件之后,我们分析其调用:

image.png

在调用StringValue.rawValue.getter方法时,实质是调用了apply %6(%5)%5StringValue.a!enumult,而%6对应方法的实现为:

image.png

将传入的值与StringValue进行匹配,因为我们传入的StringValue.a!enumult,所以会匹配上case #StringValue.a!enumult: bb1,然后会执行bb1对应的方法:

image.png

可以看到bb1直接拿到了一个字符串常量a,而一般常量是存储在MachO文件中的cstring中:

image.png

a字符串是直接在cstring表中通过地址找到的的,此过程可以通过汇编代码验证;

可失败初始化器

SIL中我们从enum的定义在看到有一个可失败初始化器init?(rawValue: String),也就是我们可以通过此方法来构造一个枚举变量:

var aaa = StringValue.init(rawValue: "a")
复制代码

需要注意的是,通过原始值进行枚举实例的构造时,是有可能构造失败的,因为我们传入的原始值不一定会对应某一个枚举值。因此该方法返回的是一个Optional类型的可选值,如果构造失败,则返回nil:

image.png

原始值的rawValue其实是存放在一片连续的内存空间,调用init(rawValue:)的时候,其实是从一个连续的数组中查找对应的字符串

猜你喜欢

转载自juejin.im/post/7066995334135676936
今日推荐