美文网首页
#8 swift 枚举类型

#8 swift 枚举类型

作者: JamesSawyer | 来源:发表于2018-08-29 00:45 被阅读24次

swift中的枚举( Enumerations )真的是太灵活了,感觉自己已经驾驭不了这匹野马了😭。

swift中的枚举特点:

  • 一等公民(first-class citizen)
  • 枚举是值类型,如果需要改变其成员值,需要通过 mutating 关键词
  • 支持类,结构体中所支持的计算属性(computed properties),就是其它语言中的 getter, setter 方法
  • 支持实例方法,提供枚举值相关联的功能
  • 还可以定义构造函数(mmp,太难了)
  • 还可以在原始实现的基础上扩展其功能
  • 可以遵循协议(protocols) 提供标准的功能
  • 和C以及OC不同的是,swift中的枚举成员在创建的时候不会被赋予一个默认的整型值
  • 其中涉及到的关键词和属性有: indirectCaseIterable, allCase, rawValue
  • 涉及到的知识点: 关联值, 原始值,递归枚举

1.语法

使用 enum 关键词定义枚举类型,这个和其它语言一致 例如

typescript中定义枚举:

enum Direction {
  Up, // 默认的赋值为0,底下的依次 +1
  Down,
  Left,
  Right
}

swift中: 使用 case 关键词来定义一个新的枚举成员

enum Direction {
  // Up,Down...也称之为 成员值
  case Up  // 此处不会默认的赋值 0
  case Down
  case Left
  case Right
}

// 等价于
enum Direction {
  case Up, Down, Left, Right
}

使用:

var direction = Direction.Up

// 或者
var direction: Direction = .Up

2.用Switch语句匹配枚举值

可以使用switch匹配单个枚举值

enum Direction {
  case Up, Down, Left, Right
}
var direction: Direction = .Up

switch direction {
case .Up:
  print("向上")
case .Down:
  print("向下")
case .Left:
  print("向左")
case .Right:
  print("向右")
// default语句可写 可不写
default:
  print("其它方向")
}

3.关联值(Associated Values)

作用:

  • 将其它类型的关联值和成员值一起进行存储,这样可以连同成员值一起存储额外的自定义信息
  • 每次在代码中使用该枚举成员时,还可以修改这个关联值

示例:一种商品有2种编码方式进行追踪:

  1. 按照 1-5-5-1 格式的数字('1' 表示1位数字 '5' 表示5位数字)表示商品的UPC一维条形码
  2. 使用字符串的形式QR码
enum Barcode {
  // 理解方式
  // 成员值是具有 (Int, Int, Int, Int) 类型相关联值的upc
  case upc(Int, Int, Int, Int) // 一维条形码
  // 具有 String 类型关联值的 qrCode
  case qrCode(String) // QR码
}

// 使用
// 定义一个商品的一维条形码
var productBarcode = Barcode.upc(8, 89201, 28993, 1)
// 也可以定义为一个QR码
prodictBarcode = .qrCode("ABCDEFGHEISLDK")

// 配合switch
switch productionBarcode {
  // 其中 let 表示提取变量 这个可以参考控制流switch章节
case let .upc(numberSystem, manufacturer, product, check):
  print("UPC: \(numberSystem), \(manufacturer), \(product), \(check)")
case let .qrCode(productCode):
  print("QR code: \(productCode)")
}

4.迭代枚举类型(Iterating over Enumeration)

有时候我们可能需要将枚举中所有的case情况组成一个集合,可以让枚举类型扩展CaseIterable 协议。

另外swift通过 allCases 属性暴露了枚举类型中所有case 的集合:
注意 Xcode 10.0+版本才支持这个属性

// 扩展 CaseIterable 协议
enum Beverage: CaseIterable {
  case coffee, tea, juice
}

// allCases 属性暴露了枚举中cases集合
let numberOfChoices = Beverage.allCases.count // 3

// 使用for-in进行迭代
for beverage in Beverage.allCases {
  print(beverage)
}
// coffee
// tea
// juice

5.原始值(Raw Values)

作为关联值的替代选择,枚举成员可以被默认值(也称为原始值)预填充,这些原始值的类型必须相同

原始值的理解: 即定义枚举的时候,把枚举的类型也定义了,比如 enum Color: String, 定义其类型为 String 类型

和关联值的区别:

  • 关联值是创建一个局域枚举成员的常量或变量时才设置值,关联值可以变化
  • 原始值针对特定的枚举成员类型,原始值会预先填充值,并且始终不变

示例:使用ASCII码作为原始值的枚举

// 这里使用Character类型作为原始值类型
// 还可以是 字符串,整型或者浮点类型
enum ASCIIControlChar: Character {
  case tab = "\t"
  case lineFeed = "\n"
  case carriageReturn = "\r"
}

原始值的隐式赋值

当原始值类型为整型或者字符串类型时,不需要显式的给每个枚举成员设置原始值,swift会自动的为你赋值

enum Direction: Int {
  // 依次 +1 进行类推
  case Up = 1, Down, Left, Right
}

使用 rawValue 属性可以访问枚举成员的原始值:

var left: Direction = .Left
// 原始值
left.rawValue // 3

字符串类型隐式的为该枚举成员的名称

enum CompassPoint: String {
  case ease, south, west, north
}

// 使用 rawValue
let north = CompassPoint.north.rawValue // "north"

使用原始值初始化枚举类型

如果枚举类型使用了原始值,自动获取一个初始化方法(呵呵,什么鬼),这个方法接收一个 rawValue 的参数,参数类型即为原始值类型,返回值则是枚举成员或 nil

另外,原始值构造器是一个可失败构造器(failable initializer)

例如,调用构造器创建一个新的枚举实例

enum Direction: Int {
  // 依次 +1 进行类推
  case Up = 1, Down, Left, Right
}

// 使用构造器,参数为rawValue 创建一个枚举实例
let possibleDirection = Direction(rawValue: 3)
// possibleDirection 的类型为 Direction? (可选类型)
// 值为 Direction.Left

// 如果不存在该值,这表示构造失败
let antherDirection = Direction(rawValue: 10)
// possibleDirection 的类型为 Direction
// 值为 nil

6.递归枚举

特点:

  • 递归枚举是一种枚举类型
  • 它有一个或多个枚举成员使用 枚举类型的实例作为关联值
  • 编译器会插入一个间接层
  • 可以在枚举成员前加上 indirect 来表示该成员可递归
  • 也可以在枚举类型的开头加上 indirect 关键词表示所有枚举成员都可递归
// 部分枚举成员可递归枚举
// 上面示例中 3个成员 都是 关联值
enum ArithExpression {
  case number(Int)
  // 使用一个或多个枚举成员的实例作为关联值
  // 使用 indirect 关键词
  indirect case addition(ArithExpression, ArithExpression)
  indirect case multi(ArithExpression, ArithExpression)
}

// 在 enum 前加上 'indirect' 表示所有枚举成员都可递归枚举
indirect enum ArithExpression {
  case number(Int)
  case addition(ArithExpression, ArithExpression)
  case multi(ArithExpression, ArithExpression)
}

// 使用
let five = ArithExpression.number(5)
let four = ArithExpression.number(4)
let sum = ArithExpression.addition(five, four)
let multiResult = ArithExpression.multi(sum, ArithExpression.number(2))

要操作具有递归性质的数据结构,使用递归函数事一种直接的方式:

func evaluate(_ expression: ArithExpression) -> Int {
  switch expression {
  case let .number(value):
    return value
  case let .addition(left, right):
    return evaluate(left) + evaluate(right)
  case let .multi(left, right):
    return evaluate(left) * evaluate(right)
  }
}

感觉这个这么复杂,估计用到的地方也比较少,了解即可

8.使用mutating 改变枚举成员的值

因为枚举类型是值类型,赋值一般都是通过拷贝的方式,所以原来的值不会改变,swift中提供了 mutating 关键词用来改变值类型的值

// 风扇开关
// 有3个档位 Off, Low, High
// next 方法用来 表示其下一档位
enum FanSwitch {
  case Off, Low, High
  mutating func next() {
    switch self {
    case .Off:
      self = .Low
    case .Low:
      self = .High
    case .High:
      self = .Off
    }
  }
}

// 定义为 Low 档位
var fan = FanSwitch.Low

fan.next()  // High
fan.next()  // Off
fan.next()  // Low

8.枚举是值类型

enum CompassPoint {
    case North, South, East, West
}
var currentDirection = CompassPoint.West
// 将上面的枚举实例赋值给另一个常量 通过拷贝的方式
let rememberedDirection = currentDirection
// 改变原来的枚举变量的值
currentDirection = .East

// 并不会影响到其赋值的值
if rememberedDirection == .West {
    print("The remembered direction is still .West")
}
// 打印 "The remembered direction is still .West"

9.关于枚举其它

可选类型是一个泛型枚举

其结构大致如下

enum Optional<T> {
  case None
  case Some(T) // 关联值
}

// 示例1
var str: String? = nil
// 等价于
var str = Optional<String>.None

// 示例2
var str2: String? = "Holo"
// 等价于
var str2 = Optional<String>.Some("Holo")

// 对于可选类型 需要解包
var showStr = str2!
// 这个过程等价于
switch str2 {
  case Some(let value):
    showStr = value
  case None:
    // 解包发生异常
}

枚举内部访问case

enum Turn {
  case left
  case right
  var reminder: String {
    switch self {
    case .left:
      return "左转"
    case .right
      return "右转"
    }
  }
}

类型属性(静态属性或者类属性)

enum SomeEnum {
  static var storedTypeProty = 10
  static var computedTypeProperty: Int {
    // get, set 方法
  }
}

相关文章

  • Swift 基础笔记 - 枚举

    枚举 OC定义和使用枚举 Swift定义枚举类型 Swift判断枚举类型 枚举成员类型

  • #8 swift 枚举类型

    极客swift 这个没有将迭代功能 swift V4.2 官方 swift中的枚举( Enumerations )...

  • Swift - 枚举

    Swift - 枚举 枚举在C和Swift中有所不同, Swift中的枚举, 更加灵活, 更加强大 C 值类型: ...

  • swift4.1 系统学习十二 枚举

    /*枚举 swift的枚举类型也是一个很强大的类型,与其他语言相比,swift中枚举应用更加灵活、广泛。 例如:像...

  • Swift基础语法-枚举,枚举原始值,枚举相关值,switch提

    1. Swift枚举基本概念 Swift中的枚举比OC中的枚举强大, 因为Swift中的枚举是一等类型, 它可以像...

  • swift3.0- 枚举

    Swift枚举 Swift中的枚举比OC中的枚举强大, 因为Swift中的枚举是一等类型, 它可以像类和结构体一样...

  • 枚举

    Swift枚举:Swift中的枚举比OC中的枚举强大, 因为Swift中的枚举是一等类型, 它可以像类和结构体一样...

  • Swift 5.1 (8) - 枚举类型

    Enumeration:枚举类型 一个枚举类型是为一组相关联的值定义的一个公共类型,使得这些关联值能够在代码中以类...

  • Swift 5.1 (8) - 枚举类型

    级别: ★☆☆☆☆标签:「iOS」「Swift 5.1」「枚举」「迭代枚举」「枚举关联值」「递归枚举」作者: 沐灵...

  • 从零学习Swift 02:枚举和可选项

    一:枚举 枚举的定义Swift中的枚举定义枚举类型很简单: 同 OC不同的是,Swift中的枚举不单单可以是Int...

网友评论

      本文标题:#8 swift 枚举类型

      本文链接:https://www.haomeiwen.com/subject/hxgcwftx.html