Swift底層原理-枚舉

Swift底層原理-枚舉

枚舉基本用法

  • Swift中可以通過enum 關(guān)鍵字來聲明一個(gè)枚舉鲤妥,如下:
enum Season {
    case spring
    case summer
    case autumn
    case winter
}

var season: Season = .spring

原始值

  • 枚舉的原始值特性可以將枚舉值與另一個(gè)數(shù)據(jù)類型進(jìn)行綁定
  • Swift中的枚舉則更加靈活杆逗,并且不需要給枚舉中的每一個(gè)成員都提供值荸型,如果要為枚舉成員提供值,那么這個(gè)值可以是字符串挎扰,字符或者浮點(diǎn)類型等等氓轰;
enum Season: String {
    case spring = "spring"
    case summer = "summer"
    case autumn = "autumn"
    case winter = "winter"
}

var season: Season = .spring
print(season.rawValue)

打印結(jié)果:spring

  • 在枚舉 Season 的后面加上 : 并指定具體的類型峰伙,這個(gè)時(shí)候枚舉的原始值默認(rèn)就是指定的類型。我們可以通過rawValue拿到枚舉成員的原始值程帕。

隱式原始值

  • 如果枚舉的原始值類型是 Int住练、StringSwift會(huì)自動(dòng)分配原始值骆捧,隱式 RawValue 分配是建立在 Swift 的類型推斷機(jī)制上的澎羞。

String類型

  • 例如枚舉Season可以如下定義
enum Season: String {
    case spring
    case summer
    case autumn
    case winter
}

print(Season.spring.rawValue) // spring
print(Season.summer.rawValue) // summer
print(Season.autumn.rawValue) // autumn
print(Season.winter.rawValue) // winter
  • 默認(rèn)將原始值設(shè)置為枚舉值一樣

Int類型

  • 如果枚舉Seacon定義為如下
enum Season: Int {
    case spring
    case summer
    case autumn
    case winter
}

print(Season.spring.rawValue) // 0
print(Season.summer.rawValue) // 1
print(Season.autumn.rawValue) // 2
print(Season.winter.rawValue) // 3
  • 枚舉的原始值是 Int 類型的,自動(dòng)分配的原始值從第一個(gè)成員開始敛苇,下標(biāo)從 0 計(jì)算妆绞,依次 +1
  • 如果假設(shè)把autumn指定為5,那么從autumn開始枫攀,下標(biāo)從5開始計(jì)算括饶,依次+1
enum Season: Int {
    case spring
    case summer
    case autumn = 5
    case winter
}

print(Season.spring.rawValue) // 0
print(Season.summer.rawValue) // 1
print(Season.autumn.rawValue) // 5
print(Season.winter.rawValue) // 6

關(guān)聯(lián)值

  • Swift中枚舉值可以跟其他類型關(guān)聯(lián)起來存儲(chǔ)在一起,從而來表達(dá)更復(fù)雜的案例来涨。
enum Season {
    case spring(month: Int)
    case summer(startMonth: Int, endMonth: Int)
}
  • 我們可以在枚舉值后面跟上你需要的一些參數(shù)图焰,比如說summer關(guān)聯(lián)了起始月份和中止月份兩個(gè)參數(shù)
var sping: Season = Season.spring(month: 1)
switch sping {
case .spring(let month):
    print(month)
case .summer(let startMonth, let endMonth):
    print(startMonth, endMonth)
}
  • 在使用 switch 的時(shí)候,我們可以在 case 的后面加上 let 或者 var 蹦掐,將枚舉的關(guān)聯(lián)值取出或者修改技羔。

關(guān)聯(lián)值和原始值的區(qū)別

  • 枚舉的關(guān)聯(lián)值和原始值在本質(zhì)上的區(qū)別就是,關(guān)聯(lián)值占用枚舉的內(nèi)存卧抗,而原始值不占用枚舉的內(nèi)存藤滥。

  • 并且 rawValue 本質(zhì)上是一個(gè)計(jì)算屬性。舉個(gè)例子社裆,rawValue的實(shí)現(xiàn)大概應(yīng)該是這樣子的:

enum Season: Int {
    case spring, summer, autumn , winter

    var rawValue: Int {
        get {
            switch self {
                case .spring:
                    return 10
                case .summer:
                    return 20
                case .autumn:
                    return 30
                case .winter:
                    return 40
            }
        }
    }
}

枚舉內(nèi)存大小

  • 接下來我們探討一下枚舉的內(nèi)存大小拙绊,探討的過程中分三種情況:第一種是無關(guān)聯(lián)值的枚舉;第二種是只有一個(gè)關(guān)聯(lián)值的枚舉;第三種是有多個(gè)關(guān)聯(lián)值的枚舉标沪。

無關(guān)聯(lián)值的枚舉

enum Season {
    case spring
    case summer
    case autumn
    case winter
}

print(MemoryLayout<Season>.size) // 1
print(MemoryLayout<Season>.stride) // 1
  • 通過打印榄攀,當(dāng)前枚舉的內(nèi)存大小為1個(gè)字節(jié)。無關(guān)聯(lián)值的枚舉默認(rèn)是以一個(gè)字節(jié)的方式去存儲(chǔ)金句,1個(gè)字節(jié)可以存儲(chǔ)256個(gè)case檩赢。如果超出這個(gè)現(xiàn)實(shí),枚舉會(huì)升級成2個(gè)字節(jié)去存儲(chǔ)趴梢。

只有一個(gè)關(guān)聯(lián)值的枚舉

enum Season {
    case spring(Bool)
    case summer
    case autumn
    case winter
}

print(MemoryLayout<Season>.size) // 1
print(MemoryLayout<Season>.stride) // 1
  • 當(dāng)枚舉的關(guān)聯(lián)值為Bool類型時(shí)漠畜,枚舉只占 1 個(gè)字節(jié)。對于Bool類型來說坞靶,它本身是 1 個(gè)字節(jié)的大小憔狞,但實(shí)際上它只需要 1 位來存儲(chǔ)Bool值,而且由于此時(shí)的枚舉是以UInt8的方式進(jìn)行存儲(chǔ)彰阴,在這 8 位當(dāng)中瘾敢,有 1 位是用來存儲(chǔ)Bool值的,余下的 7 位才是用來存儲(chǔ)case的尿这,那此時(shí)這個(gè)枚舉最多只能有 128 個(gè)case簇抵。
  • 當(dāng)枚舉的關(guān)聯(lián)值為int類型時(shí)
enum Season {
    case spring(Int)
    case summer
    case autumn
    case winter
}

print(MemoryLayout<Season>.size) // 9
print(MemoryLayout<Season>.stride) // 16
  • 當(dāng)枚舉的關(guān)聯(lián)值為Int類型時(shí),枚舉占用 9 個(gè)字節(jié)射众。對于Int類型來說碟摆,其實(shí)系統(tǒng)是沒有辦法推算當(dāng)前負(fù)載所要使用的位數(shù),這個(gè)時(shí)候我們就需要額外開辟內(nèi)存空間來存儲(chǔ)我們的case值叨橱。

多個(gè)關(guān)聯(lián)值的枚舉

enum Season1 {
    case spring(Bool)
    case summer(Bool)
    case autumn(Bool)
    case winter(Bool)
}

enum Season2 {
    case spring(Int)
    case summer(Int)
    case autumn(Int)
    case winter(Int)
}

enum Season3 {
    case spring(Bool)
    case summer(Int)
    case autumn
    case winter
}

enum Season4 {
    case spring(Int, Int, Int)
    case summer
    case autumn
    case winter
}

print(MemoryLayout<Season1>.size) // 1
print(MemoryLayout<Season2>.size) // 9
print(MemoryLayout<Season3>.size) // 9
print(MemoryLayout<Season4>.size) // 25
  • 如果枚舉中多個(gè)成員有關(guān)聯(lián)值典蜕,且最大的關(guān)聯(lián)值類型大于 1 個(gè)字節(jié)(8 位)的時(shí)候,此時(shí)枚舉的大小為:最大關(guān)聯(lián)值的大小 + 1罗洗。

特殊情況

enum Season {
    case season
}

print(MemoryLayout<Season>.size)  // 0
  • 對于當(dāng)前的Season只有一個(gè)case愉舔,此時(shí)不需要用任何東?來去區(qū)分當(dāng)前的case,所以當(dāng)我們打印當(dāng)前的Season大小是 0伙菜。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末轩缤,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子贩绕,更是在濱河造成了極大的恐慌火的,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,188評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件淑倾,死亡現(xiàn)場離奇詭異卫玖,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)踊淳,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,464評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人迂尝,你說我怎么就攤上這事脱茉。” “怎么了垄开?”我有些...
    開封第一講書人閱讀 165,562評論 0 356
  • 文/不壞的土叔 我叫張陵琴许,是天一觀的道長。 經(jīng)常有香客問我溉躲,道長榜田,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,893評論 1 295
  • 正文 為了忘掉前任锻梳,我火速辦了婚禮箭券,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘疑枯。我一直安慰自己辩块,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,917評論 6 392
  • 文/花漫 我一把揭開白布荆永。 她就那樣靜靜地躺著废亭,像睡著了一般。 火紅的嫁衣襯著肌膚如雪具钥。 梳的紋絲不亂的頭發(fā)上豆村,一...
    開封第一講書人閱讀 51,708評論 1 305
  • 那天,我揣著相機(jī)與錄音骂删,去河邊找鬼掌动。 笑死,一個(gè)胖子當(dāng)著我的面吹牛桃漾,可吹牛的內(nèi)容都是我干的坏匪。 我是一名探鬼主播,決...
    沈念sama閱讀 40,430評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼撬统,長吁一口氣:“原來是場噩夢啊……” “哼适滓!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起恋追,我...
    開封第一講書人閱讀 39,342評論 0 276
  • 序言:老撾萬榮一對情侶失蹤凭迹,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后苦囱,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體嗅绸,經(jīng)...
    沈念sama閱讀 45,801評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,976評論 3 337
  • 正文 我和宋清朗相戀三年撕彤,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了鱼鸠。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片猛拴。...
    茶點(diǎn)故事閱讀 40,115評論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖蚀狰,靈堂內(nèi)的尸體忽然破棺而出愉昆,到底是詐尸還是另有隱情,我是刑警寧澤麻蹋,帶...
    沈念sama閱讀 35,804評論 5 346
  • 正文 年R本政府宣布跛溉,位于F島的核電站,受9級特大地震影響扮授,放射性物質(zhì)發(fā)生泄漏芳室。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,458評論 3 331
  • 文/蒙蒙 一刹勃、第九天 我趴在偏房一處隱蔽的房頂上張望堪侯。 院中可真熱鬧,春花似錦深夯、人聲如沸抖格。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,008評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽雹拄。三九已至,卻和暖如春掌呜,著一層夾襖步出監(jiān)牢的瞬間滓玖,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,135評論 1 272
  • 我被黑心中介騙來泰國打工质蕉, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留势篡,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,365評論 3 373
  • 正文 我出身青樓模暗,卻偏偏與公主長得像禁悠,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子兑宇,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,055評論 2 355

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