美文网首页swift
Swift基础3(枚举)

Swift基础3(枚举)

作者: SunshineBrother | 来源:发表于2019-11-18 11:52 被阅读0次

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

    你可以用 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个字节。其实如果不设置关联值,枚举的大小就是一个字节。

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

    • 1、先打印出a的内存地址:Mems.ptr(ofVal: &a)
    • 2、打断点->右击->view Memory of a
    • 3、输入打印出来的内存地址
    屏幕快照 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)
    
    

    总结

    • 1、枚举中有一个字节存储成员值
    • 2、N个字节存储关联值(N取最大关联值),任何一个case的关联值都公用这N个字节

    相关文章

      网友评论

        本文标题:Swift基础3(枚举)

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