一哪雕、枚舉
1. 枚舉(enum)的基本寫(xiě)法斯嚎?
//1. 定義一
enum Direction {
case north
case south
case east
case west
}
//2. 定義二
enum Direction2 {
case north, south, east, west
}
//3. 使用枚舉
var dir = Direction.west
dir = Direction.east
dir = .south
print(dir)
2. 枚舉(enum)的關(guān)聯(lián)值(Associated Value)挨厚?
- 有時(shí)會(huì)將
枚舉的成員值
跟其他類(lèi)型的值
關(guān)聯(lián)存儲(chǔ)在一起疫剃,會(huì)非常有用
enum Score {
case points(Int)
case grade(Character)
}
var score = Score.points(96)
score = .grade("A")
switch score {
case let .points(i):
print(i, "Points")
case let .grade(i):
print("grade",i)
}
3. 枚舉(enum)的原始值(Raw Values)巢价?
- 枚舉成員可以使用
相同類(lèi)型的默認(rèn)值
預(yù)先關(guān)聯(lián),這個(gè)默認(rèn)值叫做:原始值
enum Grade : String {
case perfect = "A"
case great = "B"
case good = "C"
case bad = "D"
}
var studentGrade:Grade = .perfect
studentGrade = .good
print(studentGrade) // good
print(studentGrade.rawValue) // C
4. MemoryLayout 有什么用城菊?
-
MemoryLayout
可以幫助我們觀察類(lèi)型實(shí)例
的占用內(nèi)存大小
情況
-
MemoryLayout<Grade>.size
:實(shí)際占用的內(nèi)存大幸鄣纭(未進(jìn)行內(nèi)存對(duì)齊)
-
MemoryLayout<Grade>.stride
:分配的內(nèi)存大蟹ㄉ(已進(jìn)行內(nèi)存對(duì)齊)
-
MemoryLayout<Grade>.alignment
:該類(lèi)型內(nèi)存對(duì)齊的最小單位
//1.原始值
enum Grade : String {
case perfect = "A"
case great = "B"
case good = "C"
case bad = "D"
}
MemoryLayout<Grade>.size //1
MemoryLayout<Grade>.stride //1
MemoryLayout<Grade>.alignment //11
//2.關(guān)聯(lián)值
enum Password {
case number(Int, Int, Int, Int)
case other
}
MemoryLayout<Password>.size //33
MemoryLayout<Password>.stride //40
MemoryLayout<Password>.alignment //8
5. 思考為什么原始值唁奢,無(wú)論是 Int 還是 String 都只需要一個(gè)字節(jié)就能存儲(chǔ)枚舉變量麻掸?
- 因?yàn)榭梢园?rawValue 看成一個(gè)方法,代碼塊中存儲(chǔ)原始值就行了熬北。實(shí)例中不需要
6. 思考 Password
的枚舉變量讶隐,為什么 32 個(gè)字節(jié)不夠呢?
- 因?yàn)樾枰~外的 1 個(gè)字節(jié)效五,用于標(biāo)記是
number
or other
二畏妖、可選項(xiàng)(Optional)
1. 可選項(xiàng)的基本概念
- 可選項(xiàng)疼阔,一般也叫可選類(lèi)型婆廊,它允許將值設(shè)置為
nil
- 在類(lèi)型名稱(chēng)后面加個(gè)
問(wèn)號(hào) ?
來(lái)定義一個(gè)可選項(xiàng)
- 本質(zhì)其實(shí)就是
為了解決可能出現(xiàn) nil 的情況
var name: String? = "Jack"
name = nil
var age: Int? // 如果可選項(xiàng)不賦予初始值,默認(rèn)就是 nil
age = 10
age = nil
var array = [1, 15, 40, 29]
func get(_ index: Int) -> Int? {
if index < 0 || index >= array.count {
return nil
}
return array[index]
}
print(get(1)) //Optional(15)
print(get(-1)) //nil
print(get(4)) //nil
2. 什么是強(qiáng)制解包(Forced Unwrapped)否彩?
3. 什么是可選項(xiàng)綁定(Optional Binding) 列荔?
- 不使用可選項(xiàng)綁定技術(shù)的解包獲取數(shù)據(jù)
let number = Int("123") // number 的類(lèi)型是 Int?
if number != nil {
print("字符串轉(zhuǎn)換整數(shù)成功: \(number!)")
} else {
print("字符串轉(zhuǎn)換整數(shù)失敗")
}
- 使用可選項(xiàng)綁定技術(shù)獲取數(shù)據(jù)
if let number = Int("123") {
print("字符串轉(zhuǎn)換整數(shù)成功: \(number)")
//number 是強(qiáng)制解包之后的 Int 值
//number 作用域僅限于這個(gè)大括號(hào)
} else {
print("字符串轉(zhuǎn)換整數(shù)失敗")
}
- 使用可選項(xiàng)綁定代碼更加
精簡(jiǎn)
- 我們通常使用
可選項(xiàng)綁定
來(lái)判斷可選項(xiàng)是否包含值
砂吞,如果包含就自動(dòng)解包
崎溃,把值賦給一個(gè)臨時(shí)的常量 let
或者變量 var
,并返回 true
概而,否則返回 false
4. 通過(guò)下面的例子赎瑰,加強(qiáng)認(rèn)知可選項(xiàng)綁定(Optional Binding) 破镰?
- 遍歷下面的數(shù)組压储,將遇到的正數(shù)都加起來(lái)集惋,如果遇到負(fù)數(shù)或者非數(shù)字芋膘,停止變量
var strs = ["10", "20", "abc", "-20", "30"]
var strs = ["10", "20", "abc", "-20", "30"]
var index = 0
var total = 0
while let number = Int(strs[index]), number > 0 {
total += number
index += 1
}
print(total) // 30
5. 空合并運(yùn)算符 ??
(Nil-Coalescing Operator)
public func ?? <T>(optional: T?, defaultValue: @autoclosure () throws -> T?) rethrows -> T?
public func ?? <T>(optional: T?, defaultValue: @autoclosure () throws -> T) rethrows -> T
- a ?? b
- a 是可選項(xiàng)
- b 是可選項(xiàng) 或者 不是可選項(xiàng)
- b 跟 a 的存儲(chǔ)類(lèi)型必須相同
- 如果 a 不為 nil霸饲,就返回 a
- 如果 a 為 nil厚脉,就返回 b
- 如果 b 不是可選項(xiàng)傻工,就返回 a 時(shí)會(huì)自動(dòng)解包
- 總結(jié):
空合并運(yùn)算符結(jié)果的類(lèi)型取決于 b 的類(lèi)型
var a: Int? = 10
var b = 2
let c = a ?? b // c 是 Int, 值是 10
var d: Int? = nil
var e: Int? = 2
let g = d ?? e // g 是 Int?, 值是 2
6. guard 語(yǔ)句(通常用在什么情況中捆?)
- guard 語(yǔ)句特別適合用來(lái)
提前退出
guard 條件 else {
//do something
退出當(dāng)前作用域
// return坊饶、break匿级、continue痘绎、throw error
}
- 當(dāng) guard 語(yǔ)句的條件為 false 時(shí),就會(huì)執(zhí)行大括號(hào)里面的代碼
- 當(dāng) guard 語(yǔ)句的條件為 true 時(shí)尔苦,就會(huì)跳過(guò) guard 語(yǔ)句
- 當(dāng) guard 語(yǔ)句進(jìn)行可選項(xiàng)綁定時(shí)允坚,綁定的常量 let屋讶、變量 var 也能在外層作用域中使用
7. 隱式解包(Implicitly Unwrapped Optional)
- 比較少用须教,了解即可斩芭,如果非要用划乖,還不如直接用非可選項(xiàng)類(lèi)型
- 大致用法如下琴庵,可自動(dòng)解包迷殿,但是保證非
nil
let num1: Int! = 10
let num2: Int = num1
if num1 != nil {
print(num1 + 6) //直接使用庆寺,不需要解包
}
if let num3 = num1 {
print(num3)
}
8. 可選項(xiàng)在字符串插值或者直接打印時(shí)诉字,編譯器會(huì)發(fā)出警告婶肩,如何解決?(3 種思路)
var age: Int? = 10
print("My age is\(age)")
var age: Int? = 10
print("My age is\(age!)")
print("My age is\(age ?? 0)")
print("My age is\(String(describing: age))")
9. 多重可選項(xiàng)踊挠,以及如何查看多重可選項(xiàng)結(jié)構(gòu)止毕?