认识Swift系列4之枚举

2019-07-11  本文已影响0人  Niuszeng

Swift中的枚举非常强大,但也会有也有点复杂,在不清楚其相关细节时,用球来总是没有那么得心应手,此文主要以代码呈现的方式秒速了swift枚举的一些特性

1定义

enum Direction1 {
    case up
    case down
    case left
    case right
}

enum Direction2 {
    case up, down, left, right
}

let d1 = Direction1.up
switch d1 {
case .up: print("d1 is up")
case .down: print("d1 is down")
default: print("d1 is none")
}

2.关联值

enum Date {
    case digit(year: Int, month: Int, day: Int)
    case string(String)
}

let d1 = Date.digit(year: 2019, month: 7, day: 10)
print(d1)
let d2 = Date.string("2019-7-10")
print(d2)

enum Password {
    case number(Int, Int, Int, Int, Int, Int)
    case string(String)
}

3.原始值

enum Grade: String {
    case perfect = "A"
    case great = "B"
    case good = "C"
    case bad
}

// 如果不给原始值,会自动取名字字符串
// 如果是字符类型Charater必须全部初始化
let g: Grade = .good // g = good、g.rawValue = C
print("g == \(g)")
print("g rawValue == \(g.rawValue)")

let g1: Grade = .bad // g = bad、g.rawValue = bad
print("g1 == \(g1)")
print("g1 rawValue == \(g1.rawValue)")


// 隐式原始值,当后边不写是会自动有隐式原始值
enum Grade1: String {
    case perfect
    case great
    case good
    case bad
}
/** 等价
 enum Grade1: String {
 case perfect = "perfect"
 case great = "great"
 case good = "good"
 case bad = "bad"
 }
 */
enum Season: Int {
    case spring, summer, autumn, winter
}
/**
 enum Season: Int {
 case spring = 0
 case summer = 1
 case autumn = 2
 case winter = 3
 }
 */

enum Season1: Int {
    case spring = 1, summer = 4, autumn, winter
}
/**
 enum Season: Int {
 case spring = 1
 case summer = 4
 case autumn = 5
 case winter = 6
 }
 */

4.递归枚举

  • 枚举内部用到枚举本身,需要用 indirect 关键字声明
  • indirect 可修饰整个枚举、也可修饰部分枚举成员
indirect enum AddEnum1 {
    case number(Int)
    case sum1(AddEnum1, AddEnum1)
    case sum2(AddEnum1, AddEnum1)
}
enum AddEnum2 {
    case number(Int)
    indirect case sum1(AddEnum2, AddEnum2)
    indirect case sum2(AddEnum2, AddEnum2)
}

func calculate(_ e: AddEnum1)->Int {
    switch e {
    case let .number(value):
        return value;
    case let .sum1(e1, e2):
        return calculate(e1) + calculate(e2);
    case let .sum2(e1, e2):
        return calculate(e1) + calculate(e2) + 10;
    }
}

let three = AddEnum1.number(3)
let four = AddEnum1.number(4)
let sum = AddEnum1.sum1(three, four)
print("递归枚举:\(calculate(sum))")

5.枚举内存探究

enum Date {
    case digit(year: Int, month: Int, day: Int) // 3*8 = 24 bytes
    case string(String) // 16 bytes
}
/** Date 内存
 digit: 需要24个字节存储关联值
 string: 需要16个字节存储关联值
 分类内存时,以最大成员值为基准,因此需要24个字节
 由于要区分类型digit和string,另需一个字节存储type
 因此实际使用 24+1 = 25,内存对其关系:24+8 = 32
 因此实际需要一个Date枚举变量需要占用 32个字节
 
 let d:Date = .digit(year: 3, month: 8, day: 10)
 0x00 00 00 00 00 00 00 03  // 前8个字节
 0x00 00 00 00 00 00 00 08  // 8个字节
 0x00 00 00 00 00 00 00 0a  // 8个字节
 0x00 00 00 00 00 00 00 00  // 最后8个字节(实际只使用一个),存储type
 */
let d:Date = .digit(year: 3, month: 8, day: 10)
print(MemoryLayout.stride(ofValue: d))  // 实际分配 32bytes
print(MemoryLayout.size(ofValue: d))    // 实际使用 25bytes
print(MemoryLayout.alignment(ofValue: d)) // 内存对其参数 8bytes
enum Season {
    case spring, summer, autumn, winter
}
let s:Season = .spring
print(MemoryLayout.stride(ofValue: s))  // 实际分配 1bytes
print(MemoryLayout.size(ofValue: s))    // 实际使用 1bytes
print(MemoryLayout.alignment(ofValue: s)) // 内存对其参数 1bytes
enum Seasonsss: String {
    case spring = "abc", summer = "bcd", autumn = "sss", winter
    var rawValue: String {
        switch self {
        case .spring:
            return "abc"
        case .summer:
            return "bcd"
        case .autumn:
            return "sss"
        case .winter:
            return "winter"
        }
    }
}

Note:注意,此处虽然有原始值,但实际上枚举变量的原始值并不占用枚举变量的内存空间
枚举变量中任然只需1个字节存储type,即需要(0, 1, 2, ...)
不论有无原始值、关联值都是如此 type:(0, 1, 2, ...)
关联值会占用枚举变量的内存,而原始值则不占用枚举变量的内存
事实上,枚举变量的原始值实现方式与类和结构体重计算属性相同,即方法实现


enum Season1: String {
    case spring, summer, autumn, winter
}
let s2:Season1 = .spring
print(MemoryLayout.stride(ofValue: s2))  // 实际分配 1bytes
print(MemoryLayout.size(ofValue: s2))    // 实际使用 1bytes
print(MemoryLayout.alignment(ofValue: s2)) // 内存对其参数 1bytes
print(s2.rawValue)
 enum Season: Int {
 case spring = 20
 case summer = 40
 case autumn
 case winter
 }

Note:类型值
注意:虽然后边写了 20 和 40,但是实际上枚举变量并不会存储该值,在内存中依然为
0,1,2,3,而20, 40则会使用rawValue计算属性(方法)实现

枚举中通常只使用一个字节存储类型值,,0-255,当超过255时,再使用枚举说明设计上有问题,应该更改方案

上一篇 下一篇

猜你喜欢

热点阅读