Swift3知識點(diǎn)梳理(一):枚舉

在許多編程語言中都存在的枚舉類型,基本都是用于定義一個(gè)具有一組數(shù)據(jù)的值拱她,且這些值是可以枚舉的。那么Swift中我們該如何定義并使用枚舉類型呢?我們從以下3個(gè)方面對Swift3中的枚舉進(jìn)行梳理擎椰。

Swift3中枚舉的3種形式


1. 無raw value且無associated value
(1)定義無raw value且無associated value的枚舉
這種枚舉類型的定義非常簡單,例如:

enum SwitchState {
case ON 
case OFF
}

它定義了開關(guān)的兩種狀態(tài): ON, OFF创肥。另外达舒,它還有一種更簡潔的定義方式:

enum SwitchState {
case ON, OFF
}

(2)初始化及使用無raw value且無associated value類型的枚舉
示例:

var state = SWitchState.ON
switch state {
case .ON: print("This is ON state.")
case .OFF: print("This is OFF state.")
}

2. 有raw value
它用于給枚舉中定義的各個(gè)對象預(yù)先定義一個(gè)值。
(1)定義有raw value的枚舉

enum ASCIIControlCharacter: Character {
case tab = "\\t"
case lineFeed = "\\n"
case carriageReturn = "\\r"
}

它定義了一個(gè)包含一系列ASCII字符的枚舉類型叹侄,同時(shí)給其中的每個(gè)對象預(yù)先定義了一個(gè)字符串類型的值巩搏。如果預(yù)先定義的值的類型一致,那么我們可以用更簡潔的方式定義趾代,例如:

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

如果預(yù)先定義的值是Int類型贯底,且值是遞增的,那么我們可以用如下方式定義:

enum Planet: Int {
case mercury = 1, venus, earth, mars, jupiter, saturn, uranus, neptune
}

(2)使用raw value 初始化有raw value的枚舉

let possiblePlanet = Planet(rawValue: 7)
// possiblePlanet is of type Planet? and equals Planet.uranus

(3)使用有raw value的枚舉的方式

let positionToFind = 11
if let somePlanet = Planet(rawValue: positionToFind) {
     switch somePlanet {
     case .earth:
        print("Mostly harmless")
     default:
        print("Not a safe place for humans")
     }
} else {
    print("There isn't a planet at position \\(positionToFind)")
}
// Prints "There isn't a planet at position 11"

關(guān)于raw value需要注意的地方如下:

  • 枚舉中定義的各值所對應(yīng)的raw value均是常量撒强,不可變化且互不相同丈甸;
  • raw value對應(yīng)的數(shù)據(jù)類型只能是String, Character, Int 或者Float類型。

3. 有associated value
在定義枚舉的時(shí)候注入一個(gè)與枚舉值相關(guān)聯(lián)的數(shù)據(jù)尿褪,這個(gè)數(shù)據(jù)以構(gòu)造方法的形式注入到對象中睦擂。
(1)定義有associated value的枚舉

enum Barcode {
case upc(Int, Int, Int, Int)
case qrCode(String)
}

(2)初始化及使用有associated value的方式

var productBarcode = Barcode.upc(8, 85909, 51226, 3)
switch productBarcode {
case let .upc(numberSystem, manufacturer, product, check):
    print("UPC : \\(numberSystem), \\(manufacturer), \\(product), \\(check).")
case let .qrCode(productCode):
    print("QR code: \\(productCode).")
}
// Prints "QR code: ABCDEFGHIJKLMNOP."

關(guān)于Associated value需要注意如下兩點(diǎn):

  • 關(guān)聯(lián)的數(shù)據(jù)變量可以是任意類型,且枚舉內(nèi)定義的值的類型可以不同杖玲;
  • 數(shù)據(jù)是變量而非常量顿仇。

Swift3中2個(gè)特殊的枚舉類型


1. Optional
(1)Optional的枚舉本質(zhì)
要定義一個(gè)Optional類型的變量有兩種方式, 第一種方式,
let userName: Optional
第二種方式是第一種方式的語法糖形式摆马,這也是最常用的定義optional的方式:
let studentName: String?
剝開事物看本質(zhì)臼闻,對于Optional其實(shí)質(zhì)就是枚舉類型《诓桑看一下蘋果官方文檔對于optional的定義:

public enum Optional : _Reflectable, NilLiteralConvertible {
case None
case Some(Wrapped)
...
}

根據(jù)定義述呐,我們可以看到Optional的本質(zhì)就是枚舉類型。
(2)空虛的nil
nil是Optional枚舉實(shí)例的一個(gè)值蕉毯,即上段代碼中的'None'值乓搬。nil有別于其它語言中的null值思犁,以及OC中的nil值,它僅僅表示的是該對象不包含值进肯,而并非指向一個(gè)不存在的對象激蹲。

關(guān)于nil的幾個(gè)注意點(diǎn):

  • 可以給任意類型的Optional對象設(shè)置為nil,而不僅僅是class類型江掩;
  • Optional對象的默認(rèn)值為nil学辱;
  • 不能給非Optional類型的變量賦值為nil

(3)?與环形!兄弟
'?'和'!'兄弟是一對非常有趣的修飾符策泣,用途非常普遍。在swift開發(fā)中抬吟,你可以經(jīng)匙沤担看到它們兄弟在代碼中出沒的身影,可以說哪哪都是拗军。為什么說它們有趣呢任洞?因?yàn)樗鼈冇兄浅F婷畹墓δ埽瑢τ贠ptional類型的使用非常關(guān)鍵发侵。'?'和'!'都可以用于變量聲明以及表達(dá)式中交掏,但是有著各自的作用。

  • 用途一:定義optional變量
    '?'定義的變量是optional類型刃鳄,如:let studentName: String?
    '!'定義的變量也是optional類型盅弛,如:let studentName: String! , 然而與'?'定義的變量不同的是,'?'定義的變量在使用時(shí)需要使用'!'進(jìn)行解包叔锐,而使用'!'定義的變量無需解包就可以使用挪鹏。總之愉烙,'!'定義變量的方式可以看成是使用'?'定義變量并使用'!'解包的快捷方式讨盒。需要注意的是我們應(yīng)確保使用'!'定義的變量時(shí)刻有具體的值,否則使用時(shí)會造成crash步责。

  • 用途二:用于表達(dá)式中解包
    '!'作用于表達(dá)時(shí)中時(shí)主要用于解包返顺,例如:

class Person {
    var residence: Residence?
}
class Residence {
    var numberOfRooms = 1
}
let john = Person()
let roomCount = john.residence!.numberOfRooms
// this triggers a runtime error

'?'主要用于optional chain表達(dá)中,作用也是解包蔓肯。如果當(dāng)前值為nil時(shí)表達(dá)時(shí)返回nil遂鹊,且不會造成crash,例如:

class Person {
    var residence: Residence?
}
class Residence {
    var numberOfRooms = 1
}
let john = Person()
//let roomCount = john.residence!.numberOfRooms
// this triggers a runtime error, the right way is as the following:
if let roomCount = john.residence?.numberOfRooms {
    print("John's residence has \\(roomCount) room(s).")
} else {
    print("Unable to retrieve the number of rooms.")
}
// Prints "Unable to retrieve the number of rooms."

(4)解包的三種方式

  • 解包的方法一:'!'運(yùn)算符
    例如:
var userName: String? = "Mike"
print("The user name is \\(userName!)")
  • 解包的方法二:optional binding: if let {}
    例如:
var userName: String? = "Mike"
if let name = userName {
    print("The user name is \\(name)")
}
  • 解包的方法三:optional chain:
    如前所述蔗包,我們可以使用optional chain進(jìn)行解包秉扑,這里不再具體闡述。

2. 迭代枚舉
迭代枚舉其實(shí)是具有associated value類型枚舉的一個(gè)特例调限。迭代枚舉是一個(gè)非常有意思的語法舟陆,類似于函數(shù)的嵌套迭代误澳,它允許在枚舉定義Associated value的時(shí)候,將其值定義為與當(dāng)前枚舉相同的數(shù)據(jù)類型吨娜,從而形成了一種迭代的特征。定義如下:

enum ArithmeticExpression {
case number(Int)
indirect case addition(ArithmeticExpression, ArithmeticExpression)
indirect case multiplication(ArithmeticExpression, ArithmeticExpression)
}

迭代枚舉的使用方式如下:

func evaluate(_ expression: ArithmeticExpression) -> Int {
    switch expression {
    case let .number(value):
        return value
    case let .addition(left, right):
        return evaluate(left) + evaluate(right)
    case let .multiplication(left, right):
        return evaluate(left) * evaluate(right)
    }
}
print(evaluate(product))
// Prints "18"

Swift3中枚舉的面向?qū)ο?/h4>

枚舉類型在swift中屬于一等類型淘钟,它和class以及struct共同組成swift的面向?qū)ο蟮娜髷?shù)據(jù)類型宦赠。枚舉類型雖然是值類型,但是它還是具有很多面向?qū)ο蟮奶卣鳎?/p>

  • 有構(gòu)造方法米母,可以通過使用構(gòu)造方法初始化勾扭。
  • 可以定義computed屬性;
  • 可以定義實(shí)例方法铁瞒;
  • 可以實(shí)現(xiàn)接口妙色;
  • 可以被擴(kuò)展。

鑒于篇幅與內(nèi)容的原因慧耍,具體的內(nèi)容將會在之后的swift面向?qū)ο蟮母鱾€(gè)專題中分別總結(jié)身辨。下一篇文章將會總結(jié)元組類型,即:Swift3知識梳理(二):元組類型芍碧。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末煌珊,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子泌豆,更是在濱河造成了極大的恐慌定庵,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,681評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件踪危,死亡現(xiàn)場離奇詭異蔬浙,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)贞远,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,205評論 3 399
  • 文/潘曉璐 我一進(jìn)店門畴博,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人蓝仲,你說我怎么就攤上這事绎晃。” “怎么了杂曲?”我有些...
    開封第一講書人閱讀 169,421評論 0 362
  • 文/不壞的土叔 我叫張陵庶艾,是天一觀的道長。 經(jīng)常有香客問我擎勘,道長咱揍,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,114評論 1 300
  • 正文 為了忘掉前任棚饵,我火速辦了婚禮煤裙,結(jié)果婚禮上掩完,老公的妹妹穿的比我還像新娘。我一直安慰自己硼砰,他們只是感情好且蓬,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,116評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著题翰,像睡著了一般恶阴。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上豹障,一...
    開封第一講書人閱讀 52,713評論 1 312
  • 那天冯事,我揣著相機(jī)與錄音,去河邊找鬼血公。 笑死昵仅,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的累魔。 我是一名探鬼主播摔笤,決...
    沈念sama閱讀 41,170評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼垦写!你這毒婦竟也來了籍茧?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 40,116評論 0 277
  • 序言:老撾萬榮一對情侶失蹤梯澜,失蹤者是張志新(化名)和其女友劉穎寞冯,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體晚伙,經(jīng)...
    沈念sama閱讀 46,651評論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡吮龄,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,714評論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了咆疗。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片漓帚。...
    茶點(diǎn)故事閱讀 40,865評論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖午磁,靈堂內(nèi)的尸體忽然破棺而出尝抖,到底是詐尸還是另有隱情,我是刑警寧澤迅皇,帶...
    沈念sama閱讀 36,527評論 5 351
  • 正文 年R本政府宣布昧辽,位于F島的核電站,受9級特大地震影響登颓,放射性物質(zhì)發(fā)生泄漏搅荞。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,211評論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望咕痛。 院中可真熱鬧痢甘,春花似錦、人聲如沸茉贡。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,699評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽腔丧。三九已至放椰,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間悔据,已是汗流浹背庄敛。 一陣腳步聲響...
    開封第一講書人閱讀 33,814評論 1 274
  • 我被黑心中介騙來泰國打工俗壹, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留科汗,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,299評論 3 379
  • 正文 我出身青樓绷雏,卻偏偏與公主長得像头滔,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子涎显,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,870評論 2 361

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