枚举为一组相关的值定义一个共同的类型,并容许您在代码中的以类型安全的方式中使用这些值,在 Swift 中,枚举类型是一等(first-class)类型。它们采用了不少传统上只被类所支持的特征,例如计算型属性(computed properties),用于提供关于枚举当前值的附加信息,实例方法(instance methods),用于提供和枚举所表明的值相关联的功能。枚举也能够定义构造器(initializers)来提供一个初始成员值;能够在原始的实现基础上扩展它们的功能;能够遵照协议(protocols)来提供标准的功能。安全
枚举语法less
使用enum关键字申明一个枚举类型,并将整个定义放在大括号内。ide
enum SomeEumeration { // enumeration definition goes here }
下面是一个指南针4个主要方向的例子ui
enum CompassPoint { case North case South case East case West }
多个成员能够出如今同一行上,用逗号隔开编码
enum Planet { case Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Nepturn }
每一个枚举定义了一个全新的类型。像 Swift 中其余类型同样,它们的名字(例如CompassPoint和Planet)必须以一个大写字母开头。给枚举类型起一个单数名字而不是复数名字,以便于读起来更加容易理解spa
var directionToHead = CompassPoint.West
directionToHead的类型被推断当它被CompassPoint的一个可能值初始化。一旦directionToHead被声明为一个CompassPoint,你可使用更短的点(.)语法将其设置为另外一个CompassPoint的值:code
directionToHead = .East
directionToHead的类型已知时,当设定它的值时,你能够再也不写类型名。使用显示类型的枚举值可让代码具备更好的可读性。blog
使用switch匹配枚举值字符串
匹配单个枚举值it
directionToHead = .South switch directionToHead { case .North: println("Lots of planets have a north") case .South: println("Watch out for penguins") case .East: println("Where the sun rises") case .West: println("Where the skies are blue") } // prints "Watch out for penguins”
一个switch语句必须全面。若是忽略了.West这种状况,上面那段代码将没法经过编译,由于它没有考虑到CompassPoint的所有成员。全面性的要求确保了枚举成员不会被意外遗漏。
当不须要匹配每一个枚举成员的时候,你能够提供一个默认default分支来涵盖全部未明确被提出的任何成员
let somePlanet = Planet.Earth switch somePlanet { case .Earth: println("Mostly harmless") default: println("Not a safe place for humans") } // prints "Mostly harmless”
关联值
Swift 的枚举能够存储任何类型的关联值,每一个成员的数据类型能够是各不相同的。枚举的这种特性跟其余语言中的可辨识联合(discriminated unions),标签联合(tagged unions),或者变体(variants)类似。
例如,假设一个库存跟踪系统须要利用两种不一样类型的码来跟踪商品。有些商品上标有 UPC-A 格式的条形码,它使用数字0到9.每个条形码都有一个表明“数字系统”的数字,该数字后接10个表明“标识符”的数字。最后一个数字是“检查”位,用来验证代码是否被正确扫描:
其余商品上标有 QR 码格式的二维码,它可使用任何 ISO8859-1 字符,而且能够编码一个最多拥有2,953字符的字符串:
对于库存跟踪系统来讲,可以把 UPC-A 码做为三个整型值的元组,和把 QR 码做为一个任何长度的字符串存储起来是方便的。
在 Swift 中,用来定义两种商品条码的枚举
enum Barcode { case UPCA(Int, Int, Int) case QRCode(String) }
而后可使用任何一种条码类型建立新的条码
var productBarcode = Barcode.UPCA(8, 85909_51226, 3)
以上例子建立了一个名为productBarcode的新变量,而且赋给它一个Barcode.UPCA的关联元组值(8, 8590951226, 3)。提供的“标识符”值在整数字中有一个下划线,使其便于阅读条形码。同一个商品能够被分配给一个不一样类型的条形码,
productBarcode = .QRCode("ABCDEFGHIJKLMNOP")
这时,原始的Barcode.UPCA和其整数值被新的Barcode.QRCode和其字符串值所替代。条形码的常量和变量能够存储一个.UPCA或者一个.QRCode(连同它的关联值),可是在任何指定时间只能存储其中之一。
枚举switch语句
switch productBarcode { case .UPCA(let numberSystem, let identifier, let check): println("UPC-A with value of \(numberSystem), \(identifier), \(check).") case .QRCode(let productCode): println("QR code with value of \(productCode).") } // prints "QR code with value of ABCDEFGHIJKLMNOP.”
若是一个枚举成员的全部关联值被提取为常量,或者它们所有被提取为变量,为了简洁,你能够只放置一个var或者let标注在成员名称前
switch productBarcode { case let .UPCA(numberSystem, identifier, check): println("UPC-A with value of \(numberSystem), \(identifier), \(check).") case let .QRCode(productCode): println("QR code with value of \(productCode).") } // prints "QR code with value of ABCDEFGHIJKLMNOP."
Raw Values
枚举成员能够有初始值,其中这些初始值具备相同的类型,下面是一个枚举成员存储原始 ASCII 值的例子
enum ASCIIControlCharacter: Character { case Tab = "\t" case LineFeed = "\n" case CarriageReturn = "\r" }
enum Planet: Int { case Mercury = 1, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune }
let earthsOrder = Planet.Earth.toRaw() // earthsOrder is 3
用枚举的fromRaw方法来试图找到具备特定初始值的枚举成员。这个例子经过初始值7识别Uranus
let possiblePlanet = Planet.fromRaw(7) // possiblePlanet is of type Planet? and equals Planet.Uranus
然而,并不是全部可能的Int值均可以找到一个匹配的行星。正由于如此,fromRaw方法能够返回一个可选的枚举成员。在上面的例子中,possiblePlanet是Planet?类型,或“可选的Planet”。若是你试图寻找一个位置为9的行星,经过fromRaw返回的可选Planet值将是nil:
let positionToFind = 9 if let somePlanet = Planet.fromRaw(positionToFind) { switch somePlanet { case .Earth: println("Mostly harmless") default: println("Not a safe place for humans") } } else { println("There isn't a planet at position \(positionToFind)") } // prints "There isn't a planet at position 9
这个范例使用可选绑定(optional binding),经过初始值9试图访问一个行星。if let somePlanet = Planet.fromRaw(9)语句得到一个可选Planet,若是可选Planet能够被得到,把somePlanet设置成该可选Planet的内容。在这个范例中,没法检索到位置为9的行星,因此else分支被执行。