Swift-Enum基礎
Enum,也稱「列舉」。在不少程式語言上都會有的表示形式,與Class或是Struct不同的是它更像基礎型別的「客製化有限集合」。
不過在Swift中,還保留著Class的部分特性。
參考連結
原文標題寫
Swift 3,但我覺得這個基礎型別不太會改動,大部分到Swift5都還繼續使用
基礎
enum Books {
case computer
case science
case langugae
}
宣告完就能直接使用:
let computerType = Book.computer
let computerType :Book = .computer
//宣告func參數
func whichBook( _ type: Book) {}
//使用方式
whichBook(.computer)
方法2和3這邊是使用了Swfit語言的特性,判讀出這個變數的屬性,就能省略直接
.出禮面的case
Raw Value
Swift的enum和其他語言不同的是,本身不帶變數,需要明確的定義(implicit)或隱晦(explicit)的定義 case 代表的初始值
enum Books: String {
case computer
case science
case langugae
}
[!NOTE] 假設你給訂的 type 是
String時, case computer 的 raw value 就是等於"computer"。
[!NOTE] 假設有一個 enum 定義的 type 為
Int的話,那 case 的值就是以0開始
除了預設值,也可以為enum定義值:
enum Books: String {
case computer = "Computer"
case science = "Science"
case langugae = "Language"
}
[!NOTE]
Int也能改變值,不過後續沒定義到的會自動以前一個case的值+1
使用方法:
let type = Book.computer
print(type.rawValue) // Computer
[!NOTE]
CaseIterable定義後,就能使用.allCases將所有定義好的Case都取出來
Enum Associated Value
為直接讓 case 夾帶值,做法是直接在 case 的名稱後面緊接上一個 tuple:
enum Error {
case number(Int)
case message(String)
}
定義好要帶入參數的type之後就能直接使用對應type的值:
let error : Error = .message("not found")
也能定義參數名稱與帶入多個參數:
enum Error {
case number(Int)
case message(String)
case fatal(num: Int, message: String)
}
let error : Error = .fatal(num: 404, message: "not found")
func retrieve(_ error: Error) {
switch error {
case .number(let i):
print(i)
case .message(let str):
print(str)
case .fatal(num: let I, message: let S):
print(I, S)
}
}
retrieve(error) // 404 not found
Error是常用的情境之一,知道錯誤的類型但是需要動態調整錯誤的訊息
Enum Initializer
Swift Enum和其他語言不同的地方就在這,能夠像 Class 和 struct 一樣,有自己的初始化 function。
enum Book: String {
case computer
case science
case language
static let cases: [Book] = [.computer, .science, .language]
init?(_ ix: Int) {
guard ix < Book.cases.count else {
return nil
}
self = Book.cases[ix]
}
}
這樣實例化 case 時,只要使用:
let computer = Book(0)
這時 computer 就會是 Book.computer 的 type 了,但是因為是failable initializer,所以他會是 Optional(Book.computer) 的 type。
是需要用回圈檢查所有型態的場合會用,個人經驗是在建立TableView的時候Cell呈現上有用過。
Enum Properties
另一個不同的地方,就是可以宣告自己的值。
enum ShopType {
case shopA
case shopB
var names: [String] {
switch self {
case .shopA: return ["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P"]
case .shopB: return ["I","II","III","IV","V","VI","VII","VIII","IX","X"]
}
}
}
self的意義就如同class,根據現在的值返回對應的內容
Enum Methods
也能加入func撰寫
enum BookType: String {
case computer
case science
case language
static let cases: [BookType] = [.computer, .science, .language]
init?(_ ix: Int) {
guard ix < BookType.cases.count else {
return nil
}
self = BookType.cases[ix]
}
// init without saying rawvalue
init?(_ rawValue : String) {
self.init(rawValue: rawValue)
}
func nextCase() -> BookType {
var ix = BookType.cases.index(of: self)
ix = (ix! + 1) % BookType.cases.count
return BookType.cases[ix!]
}
}
var science = BookType("science")
let nextCase = science?.nextCase()
通常會寫在Enum的方法都是跟這個Enum有相關的操作。
結語
文章拆成多個的好處就是能多更新吧,不過我用的平台不需要靠文章數量堆砌,就統一到一起。
這個Enum的操作雖然簡單,不過偶爾也會忘記。