枚舉爲一組相關的值定義一個共同的類型,並容許您在代碼中的以類型安全的方式中使用這些值,在 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分支被執行。