枚舉
1. 枚舉的基本用法
- 一般用于變量的取值就固定的幾種,比如季節(jié):春夏秋冬
enum Direction {
case north
case south
case east
case west
}
enum Direction {
case north, south, east, west
}
var dir = Direction.west
dir = Direction.east
dir = .north
print(dir)//north
switch dir {
case .north:
print("\(dir)")
case .south:
print("\(dir)")
case .east:
print("\(dir)")
case .west:
print("\(dir)")
}
2.關(guān)聯(lián)值
- 將枚舉的成員值跟其他類(lèi)型的關(guān)聯(lián)存儲(chǔ)在一起
//成績(jī)可能是具體的值爹谭; 也可能是 A B C D來(lái)表示
enum Score {
case points(Int)
case grade(Character)
}
var score = Score.points(96)
score = .grade("A")
switch score {
case let .points(i): // let: 是常量還是變量 取決自己
print(i)
case let .grade(i):
print(i)
}
enum Data {
case digit(year: Int, month: Int, day: Int)
case string(String)
}
var data = Data.digit(year: 2021, month: 1, day: 14)
data = .string("2021-01-14")
switch data {
case .digit(let year, let month, let day): // let: 那個(gè)是常量那個(gè)是變量可以自己進(jìn)行定義
print("\(year)-\(month)-\(day)")
case let .string(value):
print(value)
}
//手機(jī)密碼 分為 輸入手機(jī)密碼 和 手勢(shì)密碼
enum Password {
case number (Int, Int, Int, Int)
case gesture (String)
}
var pwd = Password.number(3, 5, 7, 9)
pwd = .gesture("123456")
switch pwd {
case let .number(p1, p2, p3, p4):
print("number is",p1, p2, p3, p4)
case let .gesture(str):
print("gesture is", str)
}
3.原始值
- 枚舉成員可以使用相同類(lèi)型的默認(rèn)值預(yù)先關(guān)聯(lián),這個(gè)默認(rèn)值叫做:關(guān)聯(lián)值
enum PokerSuit : Character {
case spade = "?"
case heart = "?"
case diamond = "?"
case club = "?"
}
var suit = PokerSuit.spade
print(suit) //spade
print(suit.rawValue) //? 通過(guò) rawValue 屬性訪問(wèn)
print(PokerSuit.club.rawValue) //?
------------------------------------------------
enum Grade : String {
case a = "A"
case b = "B"
case c = "C"
case d = "D"
}
print(Grade.a.rawValue)//A
print(Grade.b.rawValue)//B
print(Grade.c.rawValue)//C
print(Grade.d.rawValue)//D
4.隱形原始值
- 如果枚舉的原始值類(lèi)型是 Int String,swift會(huì)自動(dòng)分配原始值
enum Direction : String { // String 預(yù)先關(guān)聯(lián)的原始值 是String類(lèi)型
case north = "north"
case south = "south"
case east = "east"
case west = "west"
}
||
enum Direction : String {
case north, south, east, west
}
print(Direction.north) //north
print(Direction.south.rawValue) //south
enum Season : Int {
case spring, summer, autumn, winter
}
print(Season.spring.rawValue)//0
print(Season.summer.rawValue)//1
print(Season.autumn.rawValue)//2
print(Season.winter.rawValue)//3
-----------------------------------------------
enum Season : Int {
case spring = 1, summer, autumn = 4, winter
}
print(Season.spring.rawValue)//1
print(Season.summer.rawValue)//2
print(Season.autumn.rawValue)//4
print(Season.winter.rawValue)//5
5.遞歸枚舉
- 自己用到了自己定義的類(lèi)型榛搔,必須加 indirect
indirect enum ArithExpr {
case number(Int)
case sum(ArithExpr, ArithExpr)
case difference(ArithExpr, ArithExpr)
}
------------------------------------------------
enum ArithExpr {
case number(Int)
indirect case sum(ArithExpr, ArithExpr)
indirect case difference(ArithExpr, ArithExpr)
}
let five = ArithExpr.number(5)
let four = ArithExpr.number(4)
let two = ArithExpr.number(2)
let sum = ArithExpr.sum(five, four)
let diff = ArithExpr.difference(sum, two)
//函數(shù) 計(jì)算
func calculate(_ expr: ArithExpr) -> Int {
switch expr {
case let .number(value):
return value
case let .sum(left, right):
return calculate(left) + calculate(right)
case let .difference(left, right):
return calculate(left) - calculate(right)
}
}
calculate(sum) // 9
6.MemoryLayout
- 使用MemoryLayout獲取數(shù)據(jù)類(lèi)型占用的內(nèi)存大小
- 關(guān)聯(lián)值 傳進(jìn)去的值是直接存儲(chǔ)到枚舉變量?jī)?nèi)存里
- 原始值 和成員固定綁定一起的诺凡,不會(huì)存儲(chǔ)到枚舉變量的內(nèi)存;
var age = 10
//泛型
MemoryLayout<Int>.size // 8個(gè)字節(jié)
MemoryLayout<Int>.stride //8
MemoryLayout<Int>.alignment //內(nèi)存對(duì)齊 8
||
MemoryLayout.size(ofValue: age)
MemoryLayout.stride(ofValue: age)
MemoryLayout.alignment(ofValue: age)
//關(guān)聯(lián)值 傳進(jìn)去的值是直接存儲(chǔ)到枚舉變量?jī)?nèi)存里
enum Password {
case number(Int, Int, Int, Int)
case other
}
var pwd = Password.number(4, 5, 6, 7) // 32
pwd = .other // 1
MemoryLayout.size(ofValue: pwd) // 33
MemoryLayout<Password>.size // 33 實(shí)際用到的空間大小
MemoryLayout<Password>.stride // 40 實(shí)際分配占用的空間大屑蟆(真正的)
MemoryLayout<Password>.alignment // 8 對(duì)齊參數(shù)
//----------------------------------------------------
//原始值 和成員固定綁定一起的腹泌,不會(huì)存儲(chǔ)到枚舉變量的內(nèi)存;
enum Season : Int {
case spring = 1, summer = 2, autumn = 3, winter
}
MemoryLayout<Season>.size // 1
MemoryLayout<Season>.stride // 1
MemoryLayout<Season>.alignment // 1
可選項(xiàng)
1.可選項(xiàng)(Optional)
- 可選類(lèi)型尔觉,它允許將值設(shè)置為nil
- 在類(lèi)型名稱(chēng)后面加個(gè)問(wèn)號(hào)真屯?來(lái)定義一個(gè)可選項(xiàng)
var name: String? = "jack"
name = nil
var age: Int? //默認(rèn)為nil
age = 10
age = nil
var array = [1, 2, 5, 6]
func get(_ index: Int) -> Int? {
if index < 0 || index >= array.count {
return nil
}
return array[index]
}
print(get(1)!) //2
print(get(-1)!) //nil
2.強(qiáng)制解包
- 可選項(xiàng)是對(duì)其他類(lèi)型的一層包裝,可以理解為一個(gè)盒子
- 如果為nil,那么它是個(gè)空盒子
- 如果不為nil穷娱,那么盒子里裝的是:被包裝類(lèi)型的數(shù)據(jù)
- 如果要從可選項(xiàng)中取出被包裝的數(shù)據(jù)(將盒子里裝的東西取出來(lái)),需要使用感嘆號(hào)运沦!進(jìn)行強(qiáng)制解包
var age: Int? = 10
var age1: Int = age!
age1 += 10
print(age1)
- 如果對(duì)值為nil的可選項(xiàng)(空盒子)進(jìn)行強(qiáng)制解包泵额,將會(huì)產(chǎn)生運(yùn)行時(shí)錯(cuò)誤
var age: Int?
age!
3.判斷可選項(xiàng)是否包含值
var num = Int("123")
if num != nil {
print("字符串轉(zhuǎn)換整數(shù)成功:\(num!)")//123
}else {
print("字符串轉(zhuǎn)換整數(shù)失敗")
}
4.可選項(xiàng)綁定
- 可以使用可選項(xiàng)綁定來(lái)綁定可選項(xiàng)是否包含值
- 如果包含就自動(dòng)解包,把值給一個(gè)臨時(shí)的常量(let)或者變量(var),并返回ture,否則返回false
if let number = Int("123") {
print("字符串轉(zhuǎn)換整數(shù)成功:\(number)")
//number 是強(qiáng)制解包之后的int值
//number 作用域僅限于這個(gè)大括號(hào)
}else {
print("字符串轉(zhuǎn)換整數(shù)失敗")
}
enum Season : Int {
case spring = 1, sunmmer, autumn, winter
}
---------------------------------------------------
if let season = Season(rawValue: 1) {
switch season {
case .spring:
print(season)//spring
default:
print(season)
}
} else {
print("no such season")
}
5.等價(jià)寫(xiě)法
if let first = Int("4") {
if let second = Int("42") {
if first < second && second < 100 {
print("\(first) < \(second) < 100") // 4 < 42 < 100
}
}
}
||
if let first = Int("4"),
let second = Int("42"),
first < second && second < 100 {
print("\(first) < \(second) < 100") // 4 < 42 < 100
}
6.空合并運(yùn)算符 ??
- a ?? b
- a 是可選項(xiàng)
- b 是可選項(xiàng) 或者 不是可選項(xiàng)
- b 跟 a 的儲(chǔ)存類(lèi)型必須相同
1 - 如果a 不為nil,就返回a
2 - 如果a 為nil携添,就返回b
3 - 如果b不是可選項(xiàng)嫁盲,返回a時(shí)會(huì)自動(dòng)解包
let a: Int? = 1
let b: Int? = 2
let c = a ?? b // Optional(1)
---------------------------------------------------
let a: Int? = nil
let b: Int? = 2
let c = a ?? b // Optional(2)
---------------------------------------------------
let a: Int? = nil
let b: Int? = nil
let c = a ?? b // nil
---------------------------------------------------
let a: Int? = 1
let b: Int = 2
let c = a ?? b // 1
---------------------------------------------------
let a: Int? = nil
let b: Int = 2
let c = a ?? b // 2
6.1 多個(gè) ?? 一起使用
let a: Int? = 1
let b: Int? = 2
let c = a ?? b ?? 3 // 1
---------------------------------------------------
let a: Int? = nil
let b: Int? = 2
let c = a ?? b ?? 3 // 2
---------------------------------------------------
let a: Int? = nil
let b: Int? = nil
let c = a ?? b ?? 3 // 3
6.2 ?? 跟if let 配合使用
let a: Int? = nil
let b: Int? = 2
if let c = a ?? b {
print(c) //2
}
//類(lèi)似 if a!= nil || b != nil
---------------------------------------------------
if let c = a, let d = b {
print(c)
print(d)
}
//類(lèi)似 if a != nil && b != nil
7.guard 語(yǔ)句
- 當(dāng) guard 語(yǔ)句的條件為false時(shí),就會(huì)執(zhí)行大括號(hào)里面的代碼
- 當(dāng) guard 語(yǔ)句的條件為true時(shí)烈掠,就會(huì)跳過(guò)guard語(yǔ)句
- guard語(yǔ)句特別適合用來(lái)“提前退出”
guard 條件 else {
//do something
退出當(dāng)前作用域
// return羞秤、 break、continue左敌、throw error
}
- 當(dāng)使用guard 語(yǔ)句進(jìn)行可選項(xiàng)綁定時(shí)瘾蛋,綁定的常量(let)、變量(var)也能在外層作用域中使用
func login(_ info: [String : String]) {
guard let username = info["username"] else {
print("請(qǐng)輸入用戶(hù)名")
return
}
guard let password = info["password"] else {
print("請(qǐng)輸入密碼")
return
}
print("用戶(hù)名\(username), 密碼\(password)")
}
login(["username" : "jack", "password" : "123456"])
8.隱式解包
- 在某些情況下矫限,可選項(xiàng)一旦被設(shè)定值之后哺哼,就不會(huì)一直擁有值
- 在這種情況下佩抹,可以去掉檢查,也不必每次訪問(wèn)的時(shí)候進(jìn)行解包取董,因?yàn)樗艽_定每次訪問(wèn)的時(shí)候都有值
- 可以在類(lèi)型的后面加個(gè)感嘆號(hào)棍苹!定義一個(gè)隱式解包的可選項(xiàng)
let num1: Int! = 10
let num2: Int = num1
if num1 != nil {
print(num1 + 6)//16
}
if let num3 = num1 {
print(num3)//10
}