适度给类型起别名能够让代码更加易懂,开发效率更高,可维护性更好。
一、typealias(别名)
typealias
用来给类型起别名。
1 | typealias Byte = Int8 |
Void
的本质就是空元祖的别名:public typealias Void = ()
二、枚举
Swift枚举和C/OC语言不一样,以前写OC的时候枚举本质是int
类型,但Swift中枚举可以是多类型的。
官方建议:枚举名称使用大写,成员使用小写。
2.1. 基本用法
1 | // 定义枚举 |
2.2. 关联值
有时将枚举的成员值跟其他类型的值关联存储在一起,会非常有用.
案例:
1 | enum Score { |
let
写在枚举成员前面意味着枚举成员形参只能是常量,放在形参里面可以自定义选择是var
还是let
。
2.2. 原始值
枚举成员可以使用相同类型的默认值预先关联,这个默认值叫做:原始值。
1 | enum Direction : Character { |
如果枚举的原始值类型是Int
、String
,Swift会自动分配原始值:
1 | enum Direction : String { |
Int类型,成员值自增(类似C/OC枚举):
1 | enum Season : Int { |
2.3. 递归枚举
- 关键字:
indirect
; - 可以把需要递归枚举的成员前面加
indirect
,也可以为了方便直接加到枚举定义前面。
1 | indirect enum ArithExpr { |
三、枚举的内存布局
在Swift中查看内存占用大小及对齐方式使用枚举:MemoryLayout
:
- size:实际用到的空间大小
- stride:分配占用的空间大小
- alignment:内存对齐方式
下面的意思是,Int
在内存中占用8个字节,内存对齐数是8:
1 | MemoryLayout<Int>.size // 输出:8 |
查看枚举占用内存:
1 | enum Password { |
为什么是占用内存大小是33,而分配了40?
number(Int, Int, Int, Int)
占用32个字节,other
占用1个字节,所以一共只需要占用33个字节就够用了- 因为内存对齐数是8,所以分配内存的时候只能是8的倍数,而33个字节不够8的倍数,所以往高位补齐后就是40了
为什么other
占用1个字节呢?
1 | enum Season { |
- 上面代码可以看出不管类型是什么占用的内存大小都是1个字节;
- 其实本质上是关联值和原始值的区别。
结论一: 把传进去的关联值直接存储到枚举变量内存里面的,所以枚举变量是关联值的话,内存是一定和将要存储的关联值大小有关。
为了证实结论一,比较下面的两个不同类型的关联值:
1 | enum Password { |
结论二: 原始值固定后是不能修改的,内存中只会把对应的成员值(序号)存下来,这时候1个字节足够用了,和枚举类型无关(不管是Int还是String枚举都是占用一个字节)。
分析下面代码:
1 | enum Season: Int { |
疑问:成员值在内存中只占用1个字节,Int或String的原始值是怎么存下的?rawValue其实是另外一块地址。
- 关联值才会存储到枚举变量中,原始值不会占用枚举变量内存
- 我们可以通过内存地址看到前面的字节被关联值占用,关联值后面有一个字节是保存成员值
- 1个字节存储成员值(如果只有一个枚举成员则不占用内存)
- N个字节存储关联值(N取占用内存最大的关联值),任何一个case的关联值都共用这N个字节(共用体)
- 剩余字节按照对齐数补齐
Switch
的case
其实是比较枚举的成员值的