swift

Swift基础3(枚举)

2019-11-18  本文已影响0人  SunshineBrother

枚举为一组相关值定义了一个通用类型,从而可以让你在代码中类型安全地操作这些值。

你可以用 enum关键字来定义一个枚举,然后将其所有的定义内容放在一个大括号( {})中:

enum CompassPoint {
    case north
    case south
    case east
    case west
}

多个成员值可以出现在同一行中,要用逗号隔开:

enum CompassPoint {
    case north,south,east,west
}

遍历枚举情况

对于某些枚举来说,如果能有一个集合包含了枚举的所有情况就好了。你可以通过在枚举名字后面写 : CaseIterable 来允许枚举被遍历。Swift 会暴露一个包含对应枚举类型所有情况的集合名为allCases

enum CompassPoint: CaseIterable {
    case north
    case south
    case east
    case west
}

for item in CompassPoint.allCases{
    print(item)
}
print(CompassPoint.allCases.count)

//打印结果
north
south
east
west
4

关联值

枚举的成员值跟其他类型的值关联存储在一起

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

let date:Date = .digit(year: 2019, month: 10, day: 20)

原始值

枚举成员可以是哟哦那个相同类型的默认值预先对应,这个默认值叫:原始值

enum Score:String {
    case perfect = "A"
    case great = "b"
    case goods = "c"
    case bad = "d"
}

打印原始值 rawValue

print(Score.perfect.rawValue)
A

隐式原始值

当你在操作存储整数或字符串原始值枚举的时候,你不必显式地给每一个成员都分配一个原始值。当你没有分配时,Swift 将会自动为你分配值。

实际上,当整数值被用于作为原始值时,每成员的隐式值都比前一个大一。如果第一个成员没有值,那么它的值是 0 。

enum Score:String {
    case perfect
    case great
    case goods
    case bad
}
print(Score.perfect.rawValue)

perfect

在Int类型中,会默认从0开始

enum Season: Int{
    case spring
    case summer
    case autumn
    case winter
}
print(Season.spring.rawValue)
0

嵌套枚举

enum Area {
    enum DongGuan {
        case NanCheng
        case DongCheng
    }
    
    enum GuangZhou {
        case TianHe
        case CheBei
    }
}

print(Area.DongGuan.DongCheng)

方法

 enum Device {
     case iPad, iPhone, AppleTV, AppleWatch
     func introduced() -> String {
         switch self {
         case .iPad: return "iPad"
         case .iPhone: return "iPhone"
         case .AppleWatch: return "AppleWatch"
         case .AppleTV: return "AppleTV"
         }
     }
 }

 print(Device.iPhone.introduced())

iPhone

扩展

枚举也可以进行扩展。最明显的用例就是将枚举的case和method分离,这样阅读你的代码能够简单快速地消化掉enum内容,紧接着转移到方法定义:

enum Device {
    case iPad, iPhone, AppleTV, AppleWatch
    
}
extension Device: CustomStringConvertible{
    
    func introduced() -> String {
        
        switch self {
        case .iPad: return "iPad"
        case .iPhone: return "iPhone"
        case .AppleWatch: return "AppleWatch"
        case .AppleTV: return "AppleTV"
        }
    }
 
    var description: String {
        
        switch self {
        case .iPad: return "iPad"
        case .iPhone: return "iPhone"
        case .AppleWatch: return "AppleWatch"
        case .AppleTV: return "AppleTV"
        }
    }
}

print(Device.AppleTV.description)

print(Device.iPhone.introduced())

MemoryLayout

可以使用MemoryLayout获取类型所占用的内存大小

enum Season{
    case num(Int,Int,Int,Int)
    case winter
}
 
print(MemoryLayout<Season>.stride)  //40 分配占用的空间大小
print(MemoryLayout<Season>.size)    //33 实际用到的空间大小
print(MemoryLayout<Season>.alignment)//8 对其参数

枚举底层分析

我们来查看一下枚举所占内存

enum TestEnum {
    case test1
    case test2
    case test3
    case test4
    case test5
}

print(MemoryLayout<TestEnum>.stride)    1
print(MemoryLayout<TestEnum>.size)      1
print(MemoryLayout<TestEnum>.alignment) 1

这样的枚举所占内存为1个字节

如果我们把test1=1000

enum TestEnum :Int{
    case test1 = 1000
    case test2
    case test3
    case test4
    case test5
}

print(MemoryLayout<TestEnum>.stride)    //1
print(MemoryLayout<TestEnum>.size)      //1
print(MemoryLayout<TestEnum>.alignment) //1

然后打印还是1个字节。其实如果不设置关联值,枚举的大小就是一个字节。

我们来查看一下内存布局,这里需要借助一下一个小工具,具体下载地址

屏幕快照 2019-10-26 下午4.45.32.png 1AC0A0CB-08CD-4FA9-8185-5C0A824A2519.png

我们在按照上面步骤研究一下更复杂的枚举


enum TestEnum {
    case test1(Int,Int,Int)
    case test2(Int,Int)
    case test3(Int)
    case test4(Bool)
    case test5
}


print(MemoryLayout<TestEnum>.stride)    //32
print(MemoryLayout<TestEnum>.size)      //25
print(MemoryLayout<TestEnum>.alignment) //8

/*
 64 00 00 00 00 00 00 00
 01 00 00 00 00 00 00 00
 02 00 00 00 00 00 00 00
 00
 00 00 00 00 00 00 00
 */
var a = TestEnum.test1(100,2,3)
print(Mems.ptr(ofVal: &a))

/*
 64 00 00 00 00 00 00 00
 01 00 00 00 00 00 00 00
 00 00 00 00 00 00 00 00
 01
 00 00 00 00 00 00 00 00 00
 */
a = .test2(100, 1)

/*
 64 00 00 00 00 00 00 00
 00 00 00 00 00 00 00 00
 00 00 00 00 00 00 00 00
 02
 00 00 00 00 00 00 00
 */
a = .test3(100)

总结

上一篇下一篇

猜你喜欢

热点阅读