枚舉的基本用法
等價於 =>>
使用:
-------------------------------------------------------------------------------------------------------------------------------
關聯值(Associated Values)
有時會將枚舉的成員值跟其他類型的關聯存儲在一起,會非常有用
- 必要時let也可以改爲var
- 關聯值舉例
-------------------------------------------------------------------------------------------------------------------------------
原始值(Raw Values)
-------------------------------------------------------------------------------------------------------------------------------
隱式原始值(Implicitly Assigned Raw Values)
-------------------------------------------------------------------------------------------------------------------------------
遞歸枚舉(Recursive Enumeration)
枚舉裏的枚舉類型中又調用了枚舉,就是遞歸枚舉,注意要在前面加上indirect,否則報錯
等價於==>
結果是 5 + 4 - 2 = 7
-------------------------------------------------------------------------------------------------------------------------------
MemoryLayout
可以使用MemoryLayout來獲取數據類型佔用的內存大小
這裏要注意pwd爲33是因爲要多出來一個字節來區分other和上面的number。
.stride : 分配佔用的空間大小,必須是內存對齊參數alignment的整數倍,所以是40
.alignment : 內存對齊參數
.size : 實際用到的空間大小,這裏的33表示number(Int, Int, Int, Int)中的Int每個佔8個字節,總共佔32個,other佔一個字節,加起來33個字節。
這個佔用四個字節
這裏要說一下關聯值和原始值:
number(Int, Int, Int, Int) : 屬於關聯值,將傳進來的關聯值存儲到枚舉變量裏面,因爲關聯值由外部傳入,可以任意變化,需要存儲,而原始值固定默認的,不可改變
而.other : 屬於原始值,不會存儲到枚舉變量內存裏面的
-------------------------------------------------------------------------------------------------------------------------------
可選項(Optional)
注意:Swift裏一般的值是不可以直接賦值爲nil的,但是可選類型的值可以。
- 可選項,一般也叫可選類型,它允許將值設置爲nil
- 在類型名稱後面加個問號?來定義一個可選項
-> int ? 表示返回值可以爲Int也可以爲nil
-------------------------------------------------------------------------------------------------------------------------------
強制解包
- 可選項是對其他類型的一層包裝,可以將它理解爲一個盒子
- 如果爲nil,那麼它是個空盒子
- 如果不爲nil,那麼盒子裏裝的是:被包裝類型的數據
- 如果要從可選項中取出被包裝的數據(將盒子裏的東西取出來),需要使用!進行強制解包
var age : Int? = 10
var ageInt : Int = age!
ageInt += 10
- 如果對值爲nil的可選項(空盒子)進行強制解包,將會產生運行時錯誤
- 判斷可選項是否包含值
-------------------------------------------------------------------------------------------------------------------------------
可選項綁定(Optional Binding)
- 可以使用可選項綁定來判斷可選項是否包含值
- 如果包含就自動解包,把值給一個臨時的常量(let)或者變量(var), 並返回true,否則返回false
備註:Season(rawValue: 6)是指取原始值爲6的枚舉,2就會取到summer
- 等價寫法
注意:可選項綁定的並列條件不能用 && ,可以用,
-------------------------------------------------------------------------------------------------------------------------------
while循環中使用可選項綁定
-------------------------------------------------------------------------------------------------------------------------------
空合併運算符??(Nil -Coalescing Operator)
定義:
- a ?? b
- a 是可選項
- b 是可選項 或者 不是可選項
- b 跟 a 的存儲類型必須相同
- 如果 a 不爲nil,就返回 a
- 如果 a 爲nil,就返回 b
- 如果 b 不是可選項,返回 a 時會自動解包
- 舉例:
- 多個 ?? 一起使用
不可以寫成 let c = a ?? 3 ?? b,因爲 ?? 左邊必須是可選型,不能是3
-------------------------------------------------------------------------------------------------------------------------------
空合併運算符??跟 if let配合使用
- if語句實現登陸
標註:if let tmp = info["username"]中的tmp作用域只在它大括號裏,不能作用在括號外,所以要定義一個外部常量,來獲取這個值
注意:字典類型的取值比如info["username"]這種字典類型的取值爲可選類型(?),因爲如果key值寫錯,取到的值就爲nil,這時就要用到可選類型,但是數組當取-1這種超出取值範圍的錯誤值的時候,編譯器會直接報錯,不會自動轉爲可選值
-------------------------------------------------------------------------------------------------------------------------------
guard語句
- 當guard語句的條件爲false時,就會執行大括號裏的代碼
- 當guard語句的條件爲true, 就會跳過guard語句
- guard語句特別適合用來"提前退出"
- 使用guard語句進行可選項綁定時,綁定的常量(let)和變量(var)也能在外層作用域中使用
-------------------------------------------------------------------------------------------------------------------------------
隱式解包(Implicitly unWrapped Optional)
- 在某些情況下,可選項一旦被設定值之後,就會一直擁有值
- 在這種情況下,可以去掉檢查,也不必每次訪問的時候都進行解包,因爲它能確定每次訪問的時候都有值
- 可以在類型後面加個感嘆號 ! 定義一個隱式解包的可選項
let num1: Int! = 10
let num2: Int = num1
if num2 != nil {
print(num2 + 6)
}
if let num3 = num1 {
print(num3)
}
注意:隱式解包的默認值不能爲nil,否則會報錯
-------------------------------------------------------------------------------------------------------------------------------
字符串插值
- 可選項在字符串插值或者直接打印時,編譯器會發出警告
- 至少有3種方法消除警告
-------------------------------------------------------------------------------------------------------------------------------
多重可選項
=>可轉化成結構圖:
我們可以看出num2等於num3
- 可以使用lldb指令 frame variable -R 或者 fr v -R查看區別
-------------------------------------------------------------------------------------------------------------------------------
多重可選項(nil情況)
=>可轉化成結構圖:
這裏可以看出num2與num3不同:
- 可以使用lldb指令 frame variable -R 或者 fr v -R查看區別
下圖我們可以看出:
表達式1 :num2不爲nil,表達式轉化爲num1 ?? 2, num1位nil,最終得到2
表達式2 :num3爲nil,表達式轉化爲 1 ?? 2,最終得到1。
提醒一下,可能有人認爲num1 和num3同爲nil應該相同,這是錯的,因爲兩者類型不同,num1爲Int?, num3 爲Int??
var n = num3!! :這表示雙重解包,n爲Int類型。