Swift~枚舉蝙茶、可選項(xiàng)

本文源自本人的學(xué)習(xí)記錄整理與理解艺骂,其中參考閱讀了部分優(yōu)秀的博客和書籍,盡量以通俗簡(jiǎn)單的語句轉(zhuǎn)述隆夯。引用到的地方如有遺漏或未能一一列舉原文出處還望見諒與指出钳恕,另文章內(nèi)容如有不妥之處還望指教,萬分感謝蹄衷。

枚舉

枚舉的基本用法


enum Direction {
case north
case south
case east
case west
}

-------------兩段代碼等價(jià)--------------

enum Direction {
case north, south, east, west
}

基本用法.png
  • 關(guān)聯(lián)值(Associated Values)
  1. 有時(shí)會(huì)將枚舉的成員值其他類型的值關(guān)聯(lián)存儲(chǔ)在一起忧额,會(huì)非常有用
    特點(diǎn):關(guān)聯(lián)值可以隨意修改,枚舉所占內(nèi)存大小跟關(guān)聯(lián)值有直接關(guān)系
y4828.png

Int : 關(guān)聯(lián)值類型是Int
(Int,Int,Int,Int):關(guān)聯(lián)值

enum PokerSuit : Int {
case spade(Int,Int,Int,Int)
case other
}

po: 枚舉變量
var po = PokerSuit. spade(11,22,33,44)

  • 原始值(Raw Values)

枚舉成員可以使用相同類型默認(rèn)值預(yù)先關(guān)聯(lián)愧口,這個(gè)默認(rèn)值叫做:原始值
特點(diǎn):原始值是固定的睦番,不可修改;不會(huì)占用枚舉變量內(nèi)存, 因?yàn)樗淮鎯?chǔ)在枚舉變量內(nèi)存里

Character : 原始值類型是字符類型
 "?":原始值
enum PokerSuit : Character {
case spade  = "?"
case heart  = "紅"
}

po: 枚舉變量
var po = PokerSuit. spade

這里的rawValue就是獲取枚舉成員的原始值
var rawValue = PokerSuit. spade.rawValue


  • 隱式原始值(Implicitly Assigned Raw Values)
  1. 如果枚舉的原始值類型是Int 调卑、String 抡砂;Swift會(huì)自動(dòng)分配原始值

enum Direction :String {
case north = "north"
case south = "south"
case east = "east"
case west = "west"
}

-------------兩段代碼等價(jià)--------------

enum Direction :String {
case north, south, east, west
}

字符串的名字是什么,默認(rèn)關(guān)聯(lián)的值也就是這個(gè)字符串
Int類型關(guān)聯(lián)值會(huì)是:0恬涧、1注益、2搭幻、3

  • 遞歸枚舉 (Recursive Enumeration), 枚舉前需要定義 indirect 關(guān)鍵字

indirect enum ArithExpr {
    case number(Int)
    case sum(ArithExpr, ArithExpr)
    case differ(ArithExpr, ArithExpr)
}

---------------兩段代碼等同----------------

 enum ArithExpr {
    case number(Int)
   indirect case sum(ArithExpr, ArithExpr)
   indirect case differ(ArithExpr, ArithExpr)
}

  • MemoryLayout
  1. 可以使用MemoryLayout獲取數(shù)據(jù)類型占用的內(nèi)存大小
獲取Int類型在當(dāng)前架構(gòu)(arm64)實(shí)際使用內(nèi)存大小
MemoryLayout<Int>.size

獲取Int類型在當(dāng)前架構(gòu)(arm64)分配的內(nèi)存大小
MemoryLayout<Int>.stride

內(nèi)存對(duì)齊參數(shù)
MemoryLayout<Int>.alignment


var age = 20
MemoryLayout.size(ofValue: age)
MemoryLayout.stride(ofValue: age)
MemoryLayout.alignment(ofValue: age)

MemoryLayout.png

可選項(xiàng)

  • 可選項(xiàng)垢揩,一般也叫做可選類型递宅;特點(diǎn):它允許將值設(shè)置為nil,普通的可變類型初始化之后,賦值為nil編譯器會(huì)直接報(bào)錯(cuò)
  • 多應(yīng)用在不確定情況的場(chǎng)景
  • 在類型名稱后面加一個(gè)問好 ? 來定義一個(gè)可選項(xiàng)
  • 本質(zhì):可選項(xiàng)是對(duì)其他類型的一層包裝杀捻,可以將它理解為一個(gè)盒子
  • 如果為nil , 那么它是個(gè)空盒子,反之盒子里包裝的是:被包裝的類型數(shù)據(jù)

var name: String? = "逍遙侯"
name = nil

------------------------------------

var age:Int? //默認(rèn)就是nil
age = 10
age = nil

------------------------------------

利用可選類型適配數(shù)組越界

var  list = [1,2,4,9]
func get(_ index: Int) ->Int?
{
      if index < 0 || index >= list.count {
             return nil
      }
    return list[index]
}

print(get(1))   //Optional(15)
print(get(-1)) //nil
print(get(4))  //nil

可選類型和不可選類型的區(qū)別.png
  • 強(qiáng)制解包(Forced Unwrapping)

  • 如果要從可選項(xiàng)中取出被包裝的數(shù)據(jù)(將盒子里包裝的東西取出來)俩由,需要使用感嘆號(hào) 嫉髓!進(jìn)行強(qiáng)制解包

  • 強(qiáng)制解包值是訪問盒子中的值,不會(huì)對(duì)盒子有影響

  • 如果對(duì)值為nil的可選項(xiàng)進(jìn)行強(qiáng)制解包谎仲,會(huì)產(chǎn)生運(yùn)行時(shí)錯(cuò)誤


var age:Int? //默認(rèn)就是nil
age = 10

var hhage: Int = age!

hhage += 10

輸出:20

  • 判斷可選項(xiàng)是否包含值

//字符串轉(zhuǎn)Int浙垫,可能轉(zhuǎn)換成功(整數(shù)),也可能轉(zhuǎn)換失斨E怠(nil)
let number = Int("224") //number是 number夹姥?,即可選類型辙诞;

//轉(zhuǎn)換失敗number=nil, 反之成功
if number != nil {

print("字符串轉(zhuǎn)換整數(shù)成功:\(number!)")  //強(qiáng)制解包

} else {

print("字符串轉(zhuǎn)換整數(shù)失敗")

}

  • 可選項(xiàng)綁定(Optional Binding)
  1. 可以使用可選項(xiàng)綁定來判斷可選項(xiàng)是否包含值
    • 如果包含就自動(dòng)解包辙售,把值賦給一個(gè)臨時(shí)的常量(let)或者變量(var),并返回ture,否則返回false

//先將字符串強(qiáng)制轉(zhuǎn)換為Int ,如果成功返回一個(gè)包含224的可選項(xiàng),并自動(dòng)解包飞涂,最終會(huì)把224這個(gè)數(shù)值賦值給number旦部;條件判斷返回ture ; 反之返回false

if  let number = Int("224") {

print("字符串轉(zhuǎn)換整數(shù)成功:\(number!)")  //強(qiáng)制解包

} else {

print("字符串轉(zhuǎn)換整數(shù)成功")

}

  • 可選項(xiàng)綁定等價(jià)寫法: 使用逗號(hào)(,)隔開; 不能夠使用 &&
等價(jià)寫法.png
  • while循環(huán)中使用可選項(xiàng)綁定

示例:

遍歷數(shù)組,將遇到的正數(shù)都加起來较店,如果遇到負(fù)數(shù)或者非數(shù)字士八,則停止遍歷返回

var strs = ["10","13","18","abj","-2","19","0",]
var index = 0
var sum = 0

可選項(xiàng)綁定,且num大于零; 逗號(hào)表示兩個(gè)條件要同時(shí)成立
while let num = Int(strs[index]), num > 0 {

sum += num

index += 1

}

print(sum)

  • 空合運(yùn)算符: ?? (Nil - Coalescing Operator)

空合運(yùn)算符源碼定義

public func ?? <T>(optional: T?, defaultValue: @autoclosure () thorws - > T?) rethrows - > T?

public func ?? <T>(optional: T?, defaultValue: @autoclosure () thorws - > T) rethrows - > T?

簡(jiǎn)單用法:

a ?? b

a : 要求必須是可選項(xiàng)梁呈;如果不是編譯器會(huì)報(bào)??曹铃,不建議這么寫
b和a的存儲(chǔ)類型必須相同
b : 是可選項(xiàng) 或者 不是可選項(xiàng)

b是可選項(xiàng):
如果a不為nil ,就返回 a

如果a為nil捧杉,就返回 b

b不是可選項(xiàng) :
如果a不為nil 陕见,就返回a盒子中的值; 且返回a時(shí)會(huì)自動(dòng)解包
如果a為nil,就返回b

結(jié)論:空合運(yùn)算返回的類型取決于b的類型味抖,b是什么類型最終就返回什么類型

用例.png
  • 多個(gè) ?? 一起使用; 規(guī)則從左到右運(yùn)算

示例:


let a:  Int? = 1
let b: Int? = 2

let c = a ?? b ?? 3

分析: 首先會(huì)先運(yùn)算a??b, 因?yàn)閍不為空且b是可選類型评甜,所以返回可選類型a, 然后 a??3 , a不為空,3不是可選類型仔涩,最終解包a盒子中的值1忍坷;
所以c是Int類型 值為1

  • ??if let 配合使用

獲取兩個(gè)可選類型中有值得哪一個(gè)


let a: Int? = nil
let b: Int? = 2

if let c = a ?? b {
  print(c)
}

//類似于 if a != nil  || b != nil 

-----------------------------

c綁定a,a不等于空,且 d綁定b熔脂,b不等于空
if  let c = a , let d = b {
  print(c)
  print(d)
}

//類似于if a != nil  && b != nil 

  • guard語句佩研,當(dāng)要使用多次if判斷時(shí),可以考慮是用guard代替
用法.png

注意:做完事情必須退出作用域霞揉,可以使用關(guān)鍵字:return旬薯、breakcontinue适秩、throw绊序、error

  • 當(dāng)guard語句的條件為false時(shí)硕舆,就會(huì)執(zhí)行大括號(hào)里面的代碼 ?
  • 當(dāng)guard語句的條件為true時(shí)骤公,就會(huì)跳過guard語句
  • guard語句特別適合用來實(shí)現(xiàn)”提前退出
  • 當(dāng)使用guard語句進(jìn)行可選項(xiàng)綁定時(shí)抚官,綁定的常量、變量也能在外層作用域中使用

如下示例中usernamepassword可以在外層作用域訪問

guard示例.png
  • 隱式解包 (Implicitly Unwrapped Optional)
  1. 在某些情況下阶捆,可選項(xiàng)一旦被設(shè)定值之后凌节,就會(huì)一直擁有值
  2. 在這種情況下,可以去掉檢查洒试,也不一定每次訪問的時(shí)候都進(jìn)行解包刊咳,因?yàn)樗艽_定每次訪問的時(shí)候都有值
  3. 可以在類型后面加個(gè)感嘆號(hào)定義一個(gè)隱式解包的可選項(xiàng)
  4. 感嘆號(hào)和問好都代表可選類型儡司,只不過問號(hào)需要強(qiáng)制解包后才能拿到盒子里的值,而感嘆號(hào)已經(jīng)自動(dòng)對(duì)可選類型進(jìn)行了解包余指,可以直接使用

隱式解包的可選項(xiàng)
let num: Int != 10
let num1: Int = num

  • 字符串插值或空合運(yùn)算符捕犬,消除打印可選項(xiàng)的??
字符串插值解決可選項(xiàng)打印警告.png
  • 多重可選項(xiàng),可以是一個(gè)問號(hào) ? 酵镜、兩個(gè)問號(hào)?? 碉碉、 三個(gè)問號(hào)???
  1. 可以使用lldb指令frame variable -R或者fr v -R查看區(qū)別

包裝了一個(gè)Int類型的可選類型
var num1: Int? = 10

包裝了一個(gè)可選類型的可選類型,這里的??不代表空合運(yùn)算淮韭,需要注意
var num2: Int?? = num1

包裝了Int類型可選類型的可選類型, 這樣寫就等同于num2
var num3: Int?? = 30

原理圖.png

包裝了空的可選類型
var num1: Int? =nil

包裝了一個(gè)空的可選類型的可選類型垢粮,這里的??不代表空合運(yùn)算,需要注意
var num2: Int?? = num1

包裝了大的空可選類型
var num3: Int?? = nil

原理圖1.png

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末靠粪,一起剝皮案震驚了整個(gè)濱河市蜡吧,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌占键,老刑警劉巖昔善,帶你破解...
    沈念sama閱讀 206,839評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異畔乙,居然都是意外死亡君仆,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門牲距,熙熙樓的掌柜王于貴愁眉苦臉地迎上來返咱,“玉大人,你說我怎么就攤上這事牍鞠】。” “怎么了?”我有些...
    開封第一講書人閱讀 153,116評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵难述,是天一觀的道長楞艾。 經(jīng)常有香客問我参咙,道長,這世上最難降的妖魔是什么硫眯? 我笑而不...
    開封第一講書人閱讀 55,371評(píng)論 1 279
  • 正文 為了忘掉前任蕴侧,我火速辦了婚禮,結(jié)果婚禮上两入,老公的妹妹穿的比我還像新娘净宵。我一直安慰自己,他們只是感情好裹纳,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,384評(píng)論 5 374
  • 文/花漫 我一把揭開白布择葡。 她就那樣靜靜地躺著,像睡著了一般剃氧。 火紅的嫁衣襯著肌膚如雪敏储。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,111評(píng)論 1 285
  • 那天朋鞍,我揣著相機(jī)與錄音已添,去河邊找鬼。 笑死滥酥,一個(gè)胖子當(dāng)著我的面吹牛更舞,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播坎吻,決...
    沈念sama閱讀 38,416評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼缆蝉,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了瘦真?” 一聲冷哼從身側(cè)響起刊头,我...
    開封第一講書人閱讀 37,053評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎诸尽,沒想到半個(gè)月后芽偏,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,558評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡弦讽,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,007評(píng)論 2 325
  • 正文 我和宋清朗相戀三年污尉,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片往产。...
    茶點(diǎn)故事閱讀 38,117評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡被碗,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出仿村,到底是詐尸還是另有隱情锐朴,我是刑警寧澤,帶...
    沈念sama閱讀 33,756評(píng)論 4 324
  • 正文 年R本政府宣布蔼囊,位于F島的核電站焚志,受9級(jí)特大地震影響衣迷,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜酱酬,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,324評(píng)論 3 307
  • 文/蒙蒙 一壶谒、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧膳沽,春花似錦汗菜、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至痛阻,卻和暖如春菌瘪,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背阱当。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評(píng)論 1 262
  • 我被黑心中介騙來泰國打工俏扩, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人斗这。 一個(gè)月前我還...
    沈念sama閱讀 45,578評(píng)論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像啤斗,于是被迫代替她去往敵國和親表箭。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,877評(píng)論 2 345

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