枚举定义了一个通用类型的一组相关的值,使你可以在你的代码中以一个安全的方式来使用这些值。
枚举语法(Enumeration Syntax)
使用enum关键词并且把它们的整个定义放在一对大括号内:
enum SomeEumeration { // enumeration definition goes here }
以下是指南针四个方向的一个例子:
enum CompassPoint { case North case South case East case West }
多个成员值可以出现在同一行上,用逗号隔开:
enum Planet { case Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Nepturn }
像 Swift 中其他类型一样,它们的名字(例如CompassPoint和Planet)必须以一个大写字母开头。
var directionToHead = CompassPoint.West
directionToHead的类型被推断当它被CompassPoint的一个可能值初始化。一旦directionToHead被声明为一个CompassPoint,你可以使用更短的点(.)语法将其设置为另一个CompassPoint的值:
directionToHead = .East
directionToHead的类型已知时,当设定它的值时,你可以不再写类型名。使用显示类型的枚举值可以让代码具有更好的可读性。
匹配枚举值和Switch语句(Matching Enumeration Values with a Switch Statement)
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”
当不需要匹配每个枚举成员的时候,你可以提供一个默认default分支来涵盖所有未明确被提出的任何成员:
let somePlanet = Planet.Earth switch somePlanet { case .Earth: println("Mostly harmless") default: println("Not a safe place for humans") } // prints "Mostly harmless”
关联值(Associated Values)
你可以定义 Swift 的枚举存储任何类型的关联值,每个成员的数据类型可以是各不相同的。
在 Swift 中,用来定义两种商品条码的枚举是这样子的:
enum Barcode { case UPCA(Int, Int, Int) case QRCode(String) }
以上代码可以这么理解:
然后可以使用任何一种条码类型创建新的条码,如:
var productBarcode = Barcode.UPCA(8, 85909_51226, 3)
同一个商品可以被分配给一个不同类型的条形码,如:
productBarcode = .QRCode("ABCDEFGHIJKLMNOP")
你可以在switch的case分支代码中提取每个关联值作为一个常量(用let前缀)或者作为一个变量(用var前缀)来使用:
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.”
提取一个枚举成员的所有关联值:
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" }
注意,原始值和关联值是不相同的。当你开始在你的代码中定义枚举的时候原始值是被预先填充的值,像上述三个 ASCII 码。对于一个特定的枚举成员,它的原始值始终是相同的。关联值是当你在创建一个基于枚举成员的新常量或变量时才会被设置,并且每次当你这么做得时候,它的值可以是不同的。
原始值可以是字符串,字符,或者任何整型值或浮点型值。每个原始值在它的枚举声明中必须是唯一的。当整型值被用于原始值,如果其他枚举成员没有值时,它们会自动递增。
下面的枚举是对之前Planet这个枚举的一个细化,利用原始整型值来表示每个 planet 在太阳系中的顺序:
enum Planet: Int { case Mercury = 1, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune }
自动递增意味着Planet.Venus的原始值是2,依次类推。
使用枚举成员的toRaw方法可以访问该枚举成员的原始值:
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方法返回一个可选的枚举成员。
如果你试图寻找一个位置为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
2015-03-20
15:50:56