Swift Enum 簡介
Swift語言的Enum使用方式,與C++,Java等常見的程式語言無太大差異,範例如下:
//enum定義
enum MyItem {
case localItem
case cloudItem
}
//使用enum
var myItem = MyItem.cloudItem
switch myItem {
case .localItem:
// ...
case .cloudItem:
// ...
}
Associated value
而Associated value則是Swift語言的Enum中,比較特別的一個功能。你可以讓一個enum變數額外地儲存多個其他的值,且幾乎可以是任意型別。
舉例來說,我想要讓cloudItem儲存一個代表網址的字串;而localItem則儲存了一個代表檔案路徑的字串,以及代表檔案大小的Int數值:
//enum定義
enum MyItem {
//儲存在雲端的項目,只有能存取該項目的URL網址
case cloudItem(String) // URL String
//儲存在本地端的項目,有檔案路徑以及檔案大小的資訊
case localItem(String, Int) // File path, file size
}
//使用enum與其associated value
let myItem1 = MyItem.networkItem("https://www.xxx.net")
let myItem2 = MyItem.networkItem("https://www.ooo.net")
//...
let myItem3 = MyItem.localItem("/home/username/xxx.txt",1024)
在switch case中取得associated value
在使用switch case判斷enum變數的類型時,
可在後面加上括號,並寫上let或var以及變數名稱,
以取出associated value,範例如下:
switch myItem1 {
case .localItem(let filepath, let filesize):
//...
case .cloudItem(let urlString):
//...
}
在switch case以外的場合取得associated value
使用if
若只想要針對特定的enum取出associated value,也可以改使用if case
if case .localItem(let filepath, let filesize) = myItem3 {
//...
}
if case的let/var可提到前面:
if case let .localItem(filepath, filesize) = myItem3 {
//...
}
if case的後面,可加上逗號,並於逗號後面做額外的條件判斷:
if case let .localItem(filepath, filesize) = myItem3, filesize >= 128 {
//...
}
使用for
除了if case之外,還有for迴圈也可以取得associated value,範例如下
let myItems:[MyItem] = [
.networkItem("https://www.xxx.net"),
.localItem("/home/username/xxx.txt",1024),
.networkItem("https://www.yyy.net"),
//...
]
for case let .localItem(filepath, filesize) in myItems {
//...
}
for case可使用where加上條件判斷
for case let .localItem(filepath, filesize) in myItems where filesize >= 128 {
//...
}
使用guard
同樣屬於條件判斷類型的guard,也可以使用case取得associated value並做判斷
guard case let .localItem(filepath, filesize) = myItem3, filesize >= 128 else {
//return or etc ...
}
Recursive Enumerations
由於associated value可以是任何型態的變數,因此也可以是自身型態的enum,進而形成了Recursive Enumerations
要特別注意的是,associated value中用到的變數型態有自身的enum的話,要加上indirect
enum MyItem {
case cloudItem(String) // URL String
case localItem(String, Int) // File path, file size
//因為associated value用到了MyItem本身,所以要加上indirect
indirect case pairedItem(MyItem, MyItem)
}
indirect也可以加在自身的enum宣告前面,這樣即可不用在每個有使用到associated value的項目中再寫一次
//為整個enum加上indirect
indirect enum MyItem {
case cloudItem(String) // URL String
case localItem(String, Int) // File path, file size
//此處可不用再寫indirect
case pairedItem(MyItem, MyItem)
//此處可不用再寫indirect
case multipleItems([MyItem])
}
Reference
Enumeration - The Swift Programming Language (Swift 5)
Pattern Matching, Part 4: if case, guard case, for case- Crunchy Development
沒有留言:
張貼留言