Swift 中枚举的基本用法

一、枚举语法

//枚举的语法:名称需要首字母大写
enum Direction {
    case north
    case south
    case west
    case east
}
//多个成员值可以出现在同一行中,要用逗号隔开
enum Direction2 {
    case north, south, west, east
}

注意:与 OC 不同的是,Swift 中的枚举在创建时不分配默认整数值。也就是说 north、south、west、east 不等于隐式的 0、1、2 和 3

二、使用 Switch 语句来匹配枚举值

enum Direction {
    case north, south, west, east
}
//使用 Switch 语句来匹配每一个单独的枚举值
let directionToHead = Direction.south
switch directionToHead {
case .north:
    print("north")
case .south:
    print("south")
case .west:
    print("west")
case .east:
    print("east")
}

三、遍历枚举的 case

  • 可以通过在枚举名字 后面写 : CaseIterable 来允许枚举被遍历。Swift 会暴露一个包含对应枚举类型所有情况的集 合名为 allCases。
//在枚举名字: 后面写 CaseIterable,Swift 会暴露 allCase 集合
enum Direction: CaseIterable {
    case north, south, west, east
}
//遍历枚举
for dir in Direction.allCases {
    print(dir)
}
print(Direction.allCases.count)   //获取枚举所有情况的个数

四、关联值

  • 可以定义 Swift 枚举来存储任意给定类型的关联值,如果需要的话不同枚举成员关联值的类型 可以不同
//关联值
enum BarCode {
    case upc(Int, Int, Int, Int)
    case qrCode(String)
}
var productBarCode = BarCode.upc(1, 2, 3, 4)
print(productBarCode)    //打印: upc(1, 2, 3, 4)
productBarCode = .qrCode("ABSDEFGHIJK")
print(productBarCode)    //打印: qrCode("ABSDEFGHIJK")

//可以在 case 后面写 let 或者 在括号里面 写 let 定义相匹配的变量
switch productBarCode {
case .upc(let first, let second, let third, let fourth):
    print("UPC: \(first), \(second), \(third), \(fourth)")
case let .qrCode(productCode):
    print("QR code: \(productCode)")
}

五、原始值

  • 枚举成员可以用相同类型的默认值预先填充(称为原始值)

注意:如果声明的时候不指定枚举类型就没有rawValue属性(包括关联值)

//枚举也可以有原始值
enum ControlCharacter: Character {  //如果没有声明枚举的类型,是没有 rawValue 属性可以访问的
    case tab = "\t"
    case linefeed = "\n"
    case carrigeReturn = "\r"
}
print(ControlCharacter.linefeed.rawValue)  //输出结果是换行了

六、预设原始值

  • 在操作存储整数或字符串原始值枚举的时候,不必显式地给每一个成员都分配一个原始 值。当没有分配时,Swift 将会自动为你分配值
//预设原始值:预设west等于5,那么后面的值依次往后面加1
enum point: Int {
    case west = 5
    case north   // 6
    case east    // 7
    case south   // 8
}
print(point.south.rawValue)   //输出结果为:8

enum Point2: Int {
    case west
    case north
    case east = 5
    case south
}
//值得注意的是: 如果是给 east 赋值为 5, west 的值是从 0, north 的值是 1
print(Point2.south.rawValue)   // 6
print(Point2.west.rawValue)    // 0
print(Point2.north.rawValue)   // 1
//预设原始值: 必须要定义枚举的类型
enum point: String {
    case west
    case north
    case east
    case south
}
print(point.south.rawValue)   //输出结果为:south,此时可以不写 rawValue,它们输出的值是一样的

七、从原始值初始化

  • 如果用原始值类型来定义一个枚举,那么枚举就会自动收到一个可以接受原始值类型的值初始化器(叫做 rawValue的形式参数)然后返回一个枚举成员或者 nil 。你可以使用这个初始 化器来尝试创建一个枚举的新实例
//预设原始值:预设west等于5,那么后面的值依次往后面加1
enum point: Int {
    case west = 5
    case north   // 6
    case east    // 7
    case south   // 8
}
print(point.south.rawValue)   //输出结果为:8

//也可以使用rawValue来创建或者初始化一个枚举值,最终可以获取枚举的具体值
let direction2 = point(rawValue: 9)
print(direction2 ?? 0)   //如果direction2没有值的话,默认就是0

八、递归枚举

  • 递归枚举是拥有另一个枚举作为枚举成员关联值的枚举。当编译器操作递归枚举时必须插入间接寻址层。可以在声明枚举成员之前使用 indirect关键字来明确它是递归的
//如说表达式(5 + 4) * 2 在乘法右侧有一个数但有其他表达式在乘法的左侧
indirect enum Expression {
    case number(Int)
    case add(Expression, Expression)
    case multiply(Expression, Expression)
}
let four = Expression.number(4)
let five = Expression.number(5)
let sum = Expression.add(four, five)
print(four)
print(sum)
let multiply = Expression.multiply(sum, Expression.number(2))
print(multiply)
//在函数中根据switch语句获取匹配的case条件
func eval(_ expression: Expression) -> Int {
    //使用值绑定的方式
    switch expression {
    case .number(let value):
        return value
    case .add(let first, let second):
        return eval(first) + eval(second)
    case .multiply(let first, let second):
        return eval(first) * eval(second)
    }
}
print(eval(multiply))   // 18

注意: OC的枚举值只支持Int一种类型,Swift的枚举值支持四种类型: 整型(NSInteger)、浮点型(Double、Flaot)、字符串(String)、布尔类型(Bool)

十、总结

  1. Swift中的枚举很强大
  2. enum中的 rawValue 是其中的计算属性
  3. 如果声明的时候不指定枚举类型就没有rawValue属性(包括关联值)
  4. rawValue中的值存储在Mach-O中,不占用枚举的存储空间
  5. 枚举值与rawValue不是同一个东西
  6. rawValue可以不写,如果是Int默认0,1,2…String等于枚举名称的字符串
  7. 如果枚举中存在rawValue同时也会存在init(rawValue:)方法,用于通过rawValue值初始化枚举
  8. 如果枚举遵守了CaseIterable协议,且不是关联值的枚举,我们可以通过enum.allCases获取到所有的枚举,然后通过for循环遍历
  9. 我们可以使用switch对枚举进行模式匹配,如果只关系一个枚举还可以使用if case
  10. 关联值枚举可以表示复杂的枚举结构
  11. 关联值的枚举没有init方法,没有RawValue别名,没有rawValue计算属性
  12. enum可以嵌套enum,被嵌套的作用域只在嵌套内部
  13. 结构体也可以嵌套enum,此时enum的作用域也只在结构体内
  14. enum中可以包含计算属性,类型属性但不能包含存储属性
  15. enum中可以定义实例方法和使用static修饰的方法,不能定义class修饰的方法
  16. 如果想使用复杂结构的枚举,或者说是具有递归结构的枚举可以使用indirect关键字

可以参考文章 https://www.jianshu.com/p/d25860cf8757

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值