iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 12
0

https://ithelp.ithome.com.tw/upload/images/20181027/20110801u7BVQmM3Kk.png

enum 介紹

enum讓我們可以自定義一個型別的一組相關的值,讓我們可以已型別安全 ( type-safe)的方式使用這些值。enum 支援許多特性,例如計算型屬性(computed property)、實體方法(instance method)、初始化(initializer)、擴展(extension)、協定(protocol)。

https://ithelp.ithome.com.tw/upload/images/20181027/20110801yn4bQFnZnx.png

enum語法

enum 自定義型別 {
各列舉定義
}

https://ithelp.ithome.com.tw/upload/images/20181027/20110801X1GIcY0Mql.png

每個列舉都定義了一個全新的型別。像其他 Swfit 其他型別一樣,列舉的名稱應該以一個大寫字母為開頭且為單數。定義好 enum 後,指派一個變數給他:

https://ithelp.ithome.com.tw/upload/images/20181027/20110801btf4q8IhAr.png

使用 Switch 配對列舉值

https://ithelp.ithome.com.tw/upload/images/20181027/20110801QR55WJVT5U.png

遍歷 enum

我們可以透過在 enum 名字後面寫上 “ CaseIterabl ” 來允許 enum 被遍歷。而 Swift 可以使用 allCases 成為去包含所有 case 的集合。

enum Car: CaseIterable {
case bmw, benz, honda, toyota
}
var numberOfCar = Car.allCases.count
print(\numberOfCar)
//print 4

上面的例子說明了 Car 這個 enum 有多少種 case,而我們可以用 for 迴圈去遍歷所有 case:

for car in Car.allCases {
print(car)
}
//bmw
//benz
//honda
//toyota

以上語法遵循 enumeration protocol

關聯值

enum 中的 case 可以依照我門需求的不同去儲存及設定相關值

舉個例子:

https://ithelp.ithome.com.tw/upload/images/20181027/20110801qvtSntqEhO.png

有些條碼是用 0~9 的 UPC-A 格式一維條碼,每個條碼數字都含有一個 “數字系統” 位,隨後是五個 “製造商代碼“ 及 “商品代碼”,而最後一碼是用來檢測代碼已經被掃描。

https://ithelp.ithome.com.tw/upload/images/20181027/20110801nP35UEQbuR.png

其他產品貼著二維條碼,他可以使用 IOS 8859–1 字符,並最長可以使用 2953 個字串的字符
這樣可以讓系統可方便的以一個由 4 個字串所組成的元祖來儲存 UPC-A 格式條碼,然而二維條碼可以可以被儲存位一個任意長度的字串

在 Swift 中,不同類型的條碼的形式:

https://ithelp.ithome.com.tw/upload/images/20181027/201108010CUBrVi4sl.png

可以這樣讀:
宣告一個叫做 Barcode 的 enum,一個成員是 upc,夾帶著 ( Int, Int, Int, Int )型別的相關值;另一個型別為 qrCode,夾帶著 String 型別的相關值。
注意!這個定義並不存在任何實際的 integer 或 string,他定義當 Barcode 常數和變數與 Barcode.upc 或 Barcode.qrCode 相同時,可以儲存相關值的型別

這時我們可以指派型別為 Barcode 的變數:

https://ithelp.ithome.com.tw/upload/images/20181027/201108019wILPq3zGp.png

一個常數或變數同一時間只能儲存一個 enum 的成員值及其相關值!

在使用 switch 配對列舉值時,可以把相關值取出來做為常數或是變數使用:

https://ithelp.ithome.com.tw/upload/images/20181027/20110801oqcVOHDNSv.png

如果相關值同樣被取出作為常數或變數,只需要在成員名稱前面加上 let 或 var,讓程式碼更為簡潔:

https://ithelp.ithome.com.tw/upload/images/20181027/20110801IMRwQxesrv.png

原始值

除了使用相關 值的列舉,其成員值可以儲存不同型別的相關值。Swift 也提供 enum 先設定原始值 ( raw value ) 來替代相關值。這些原始值的型別必須相同,使用方法為在 enum 後面加上冒號及型別:

https://ithelp.ithome.com.tw/upload/images/20181027/201108010uclVgf348.png

原始值 ( raw value ) 和相關值 ( associated value ) 是不同的。原始值在定義 enum時就被設置,對於一個特定的成員,他的值始終是相同的;相關值是成員被指派為一個常數或是變數時才設置的值,成員的相關值是可以不同的!

原始值的隱式指派

在使用原始值是整數型別的列舉時,可以不需要為每個成員設置原始值,Swift 會自動將每個成員的值依次遞增 1,這個特性稱為原始值的隱式指派(implicitly assigned raw value)。而成員都沒有原始值時,第一個成員的原始值為 0,再依序遞增 1。

https://ithelp.ithome.com.tw/upload/images/20181027/20110801zjClYpmsFe.png

使用原始值初始化 enum

在定義 enum 時,如果使用了原始值,則這個 enum 會有一個初始化的方法,這個方法有一個名稱為 rawValue 的參數,其參數型別為列舉原始值的型別,返回值為列舉成員或 nil。

https://ithelp.ithome.com.tw/upload/images/20181027/20110801zj8uYFmjoB.png

不過不是所有的 Int 都會有回傳值,所以其實他是回傳一個 week? 類型,也就是可選的 week

https://ithelp.ithome.com.tw/upload/images/20181027/20110801HrVw09EihJ.png

上述程式使用了可選綁定 ( optional binding ),並使用原始值 8 來尋找一個星期有沒有 8 天,如果一個星期有 8 天應該是遇到世界末日了!不過我們並沒有在 week 裡面找到原始值 9 的成員,所以會回傳 nil,執行 else 的程式。

遞迴列舉

遞迴列舉 ( recursive enumeration ) 唯一種列舉型別,他會有一個或多個成員使用該列舉型別實作作為相關值。若要表示一個成員可以是遞迴的,要在成員前面加上 indirect

https://ithelp.ithome.com.tw/upload/images/20181027/20110801muaPtomIDV.png

或是我們將 indirect 放在 enum 前面,表示整個 enum 都是可以遞迴的

https://ithelp.ithome.com.tw/upload/images/20181027/201108014h0d7gxBRq.png

這個 enum 可意儲存 3 種運算表達式:單一數字、兩個表達式的加法以及兩個表達式的乘法。addition 及 nultiplication 成員擁有同樣是數學表達式的關聯值。舉個例子:數學表達式 ( 6 + 4 ) × 5,乘號右側有一個數字,左側有一個表達式:

https://ithelp.ithome.com.tw/upload/images/20181027/20110801zOQDzb6cTq.png

這裡有一個判斷數學表達式的函數:

https://ithelp.ithome.com.tw/upload/images/20181027/20110801JNAlz9wWEN.png

透過函數來回傳相關值來判斷普通數字,並透過衡量表達式左側或右側還判斷是加法還是乘法

今天的 enumeration 就到這裡囉!如果有其他的問題歡迎留言或是寄信給我!(*´∀`)


上一篇
Swift4.2 Day-11 Closure ( 2 )
下一篇
Swift4.2 Day-13 Structures and Classes
系列文
菜比八iOS程式開發30天自我挑戰30

尚未有邦友留言

立即登入留言