iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 4
0
自我挑戰組

iOS 新手開發的大小事系列 第 4

Day 4: [Swift] 列舉 (Enumerations) -1

  • 分享至 

  • xImage
  •  

前言

今天討論的主題,其實不是新東西,早在 C 語言就有列舉 (Enumerations),在 Swift 中,列舉和 switch 語句搭配使用,是很好程式碼管理的方法,但目前仍沒有實際使用過,或說不知道實際差異,就先在此把語法列出,等到真的需要時,再來參照使用。今天先寫出列舉的前半部分,明天再針對列舉的關聯值 (Associated Values) 和原始值 (Raw Values) 詳細描述。

列舉為一組相關值定義了一個共同的型別,能夠在代碼中以型別安全的方式處理這些值。

如果我們熟悉 C,便知道 C 列舉將相關名稱分配給一組整數值。 Swift 中的列舉更靈活,並且不必為列舉的每個例項提供值。如果為每個列舉例項提供了一個值(稱為原始值),則該值可以是字串,字元或任何整數或浮點類型的值。

另外,列舉項目可以指定要與每個不同的列項值一起存儲的任何型別的關聯值,就像其他語言中的聯合或變體一樣。我們可以將一組共用的相關例項設定為一個列舉的一部分,每個列舉都有一組與其關聯適當型別的不同值。

Swift 中的列舉本身就是第一級的型別。它們採用傳統上僅由類支援的許多功能,例如計算屬性用來提供有關列舉當前值的其他資訊,以及實例方法用來提供與列舉所代表的值相關的功能。列舉還可以定義初始化器以提供初始例項值;可以用擴展來擴展其功能,用以超越原本的實作;並且可以符合協議來提供標準功能。


列舉語法 (Enumeration Syntax)

將使用關鍵字 enum 引入列舉,並將其整個定義放在一對大括號中:

enum SomeEnumeration {
    // 放入列舉的定義
}

以下的範例是指南針的四個主要的方位點:

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

列舉中定義的值(例如北、南、東和西)是其列舉例項。可以使用關鍵字 case 來引入新的列舉例項。

與 C 和 Objective-C 等語言不同,Swift 列舉例項沒有預設整數值。在上面的 CompassPoint 範例中,北、南、東和西沒有隱含地等於 0, 1, 2 和 3。相反的,不同的列舉例項本身就是值,具有明確定義的 CompassPoint 型別。

多個例項可以一行表示,用逗號分隔:

enum Planet {
    case mercury, venus, earth, mars, jupiter, saturn, uranus, neptune
}

每個列舉定義都定義了一個新型別。與 Swift 中的其他型別一樣,它們的名稱(例如 CompassPointPlanet)以大寫字母開頭。給列舉型別單數名稱而不是複數名稱,使其明顯為本身所示:

var directionToHead = CompassPoint.west

CompassPoint 的可能值初始化時,可推斷出 directionToHead 的型別。將 directionToHead 宣告為 CompassPoint 後,可以使用較短的點語法將其設置為不同的 CompassPoint 值:

directionToHead = .east

已知 directionToHead 的型別,因此可以在設置其值時刪除該型別。在使用明顯型別的列舉值時,增加代碼的可讀性。


使用 Switch 語句搭配列舉值 (Matching Enumeration Values with a Switch Statement)

使用 switch 語句搭配各個列舉值:

directionToHead = .south
switch directionToHead {
case .north:
    print("Lots of planets have a north")
case .south:
    print("Watch out for penguins")
case .east:
    print("Where the sun rises")
case .west:
    print("Where the skies are blue")
}
// Prints "Watch out for penguins"

可將此代碼讀作:
「考慮 directionToHead 的值。在其值等於 .north 的例項時,印出 "Lots of planets have a north"。如果其值等於 .south,則印出 "Watch out for penguins"。」...等等。

在考慮列舉的例項時,switch 語句必須是完整的。如果省略 .west 的例項,則此代碼不會編譯,因為它沒有考慮到 CompassPoint 例項的完整列表。要求詳盡無遺確保列舉例項不會被意外遺漏。

如果不適合為每個列舉例項提供一個 case,則可以提供一個預設例項來涵蓋未明確敘述的任何例項:

let somePlanet = Planet.earth
switch somePlanet {
case .earth:
    print("Mostly harmless")
default:
    print("Not a safe place for humans")
}
// Prints "Mostly harmless"

遍歷列舉例項 (Iterating over Enumeration Cases)

對於某些列舉,擁有所有列舉例項的集合很有用。可以在列舉名稱後寫入:CaseIterable 來啟用此功能。 Swift 將所有例項的集合公開為列舉型別的屬性 allCases 。以下為一例子:

enum Beverage: CaseIterable {
    case coffee, tea, juice
}
let numberOfChoices = Beverage.allCases.count
print("\(numberOfChoices) beverages available")
// Prints "3 beverages available"

在上面的範例中,編寫 Beverage.allCases 來訪問包含 Beverage 列舉的所有例項的集合。可以像使用任何其他集合一樣使用 allCases -- 集合的元素是列舉型別的實例,因此在這種情況下,它們是 Beverage 值。上面的範例計算了有多少個案例,下面的範例使用 for 循環來迭代所有例項:

for beverage in Beverage.allCases {
    print(beverage)
}
// coffee
// tea
// juice

上一篇
Day 3: [Swift] 閉包 (Closures) -2
下一篇
Day 5: [Swift] 列舉 (Enumerations) -2
系列文
iOS 新手開發的大小事30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
ytyubox
iT邦新手 5 級 ‧ 2019-09-19 16:30:00

CaseiterableAllcases 很有趣, 他是 static varible

Jes iT邦新手 5 級 ‧ 2019-09-21 18:14:20 檢舉

怎麼知道他是 static varible

ytyubox iT邦新手 5 級 ‧ 2019-09-21 19:29:55 檢舉

基本上ClassName.property 這種寫法的就一定是type property

我要留言

立即登入留言