Swift-枚舉、可選項(xiàng)

枚舉

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
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市茵汰,隨后出現(xiàn)的幾起案子枢里,更是在濱河造成了極大的恐慌,老刑警劉巖蹂午,帶你破解...
    沈念sama閱讀 223,126評(píng)論 6 520
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件栏豺,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡画侣,警方通過(guò)查閱死者的電腦和手機(jī)冰悠,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,421評(píng)論 3 400
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)配乱,“玉大人溉卓,你說(shuō)我怎么就攤上這事“崮啵” “怎么了桑寨?”我有些...
    開(kāi)封第一講書(shū)人閱讀 169,941評(píng)論 0 366
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)忿檩。 經(jīng)常有香客問(wèn)我尉尾,道長(zhǎng),這世上最難降的妖魔是什么燥透? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 60,294評(píng)論 1 300
  • 正文 為了忘掉前任沙咏,我火速辦了婚禮,結(jié)果婚禮上班套,老公的妹妹穿的比我還像新娘肢藐。我一直安慰自己,他們只是感情好吱韭,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,295評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布吆豹。 她就那樣靜靜地躺著,像睡著了一般理盆。 火紅的嫁衣襯著肌膚如雪痘煤。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 52,874評(píng)論 1 314
  • 那天猿规,我揣著相機(jī)與錄音衷快,去河邊找鬼。 笑死坎拐,一個(gè)胖子當(dāng)著我的面吹牛烦磁,可吹牛的內(nèi)容都是我干的养匈。 我是一名探鬼主播,決...
    沈念sama閱讀 41,285評(píng)論 3 424
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼都伪,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼呕乎!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起陨晶,我...
    開(kāi)封第一講書(shū)人閱讀 40,249評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤猬仁,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后先誉,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體湿刽,經(jīng)...
    沈念sama閱讀 46,760評(píng)論 1 321
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,840評(píng)論 3 343
  • 正文 我和宋清朗相戀三年褐耳,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了诈闺。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,973評(píng)論 1 354
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡铃芦,死狀恐怖雅镊,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情刃滓,我是刑警寧澤仁烹,帶...
    沈念sama閱讀 36,631評(píng)論 5 351
  • 正文 年R本政府宣布,位于F島的核電站咧虎,受9級(jí)特大地震影響卓缰,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜砰诵,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,315評(píng)論 3 336
  • 文/蒙蒙 一征唬、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧茁彭,春花似錦鳍鸵、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,797評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)击罪。三九已至哲嘲,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間媳禁,已是汗流浹背眠副。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,926評(píng)論 1 275
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留竣稽,地道東北人囱怕。 一個(gè)月前我還...
    沈念sama閱讀 49,431評(píng)論 3 379
  • 正文 我出身青樓霍弹,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親娃弓。 傳聞我的和親對(duì)象是個(gè)殘疾皇子典格,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,982評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容