swift基礎(chǔ)-optional

轉(zhuǎn)載鏈接swift-optional
本是學(xué)習(xí)控制流時(shí)引入下optional,本來打算自己寫寫,發(fā)現(xiàn)下面作者寫的很好,很全,因?yàn)橄胧珍浀絪wift專題下方便大家學(xué)習(xí),只好搬運(yùn)過來了,再次感謝作者轉(zhuǎn)載鏈接swift-optional
Optional的定義
Optional也是Objective-C沒有的數(shù)據(jù)類型疲扎,是蘋果引入到Swift語言中的全新類型,它的特點(diǎn)就和它的名字一樣:可以有值串结,也可以沒有值拙已,當(dāng)它沒有值時(shí)金蜀,就是nil。此外,Swift的nil也和Objective-C有些不一樣源祈,在Objective-C中渔欢,只有對(duì)象才能為nil墓塌,而在Swift里,當(dāng)基礎(chǔ)類型(整形奥额、浮點(diǎn)苫幢、布爾等)沒有值時(shí),也是nil披坏,而不是一個(gè)初始值态坦,沒有初始值的值,是不能使用的棒拂,這就產(chǎn)生了Optional類型伞梯。定義一個(gè)Optional的值很容易,只需要在類型后面加上問號(hào)(?)就行了帚屉,如:

var str: String?        // 沒有值得str輸出為nil

一個(gè)Optional值和非Optional值的區(qū)別就在于:Optional值未經(jīng)初始化雖然為nil谜诫,但普通變量連nil都沒有:

//未被初始化,但是是一個(gè)Optional類型攻旦,為nil
var str: String?
str //輸出nil
//未被初始化喻旷,也不是Optional類型
var str2: String
str2    //使用時(shí)出錯(cuò)

Optional的拆包
顯式拆包
Optional類型的值不能被直接使用,當(dāng)需要用時(shí)要顯式拆包牢屋,以表明我知道這個(gè)Optional是一定有值的:

var str: String? = "Hello World!"
str! //Hello World!

對(duì)比拆包前后且预,對(duì)str的輸出:

var str: String? = "Hello World!"
str     //{Some "Hello World!"}
str!    //Hello World!

之所以要拆包使用,是因?yàn)镺ptional類型其實(shí)是一個(gè)枚舉:

enum Optional<T> : Reflectable, NilLiteralConvertible {
    case None
    case Some(T)
    init()
    init(_ some: T)

    /// Haskell's fmap, which was mis-named
    func map<U>(f: (T) -> U) -> U?
    func getMirror() -> MirrorType
    static func convertFromNilLiteral() -> T?
}

當(dāng)Optional沒有值時(shí)烙无,返回的nil其實(shí)就是Optional.None锋谐,即沒有值。除了None以外截酷,還有一個(gè)Some涮拗,當(dāng)有值時(shí)就是被Some<T>包裝的真正的值,所以我們拆包的動(dòng)作其實(shí)就是將Some里面的值取出來。
有沒有似曾相識(shí)的感覺三热?Java里面也有泛型鼓择。

隱式拆包
除了顯式拆包,Optional還提供了隱式拆包就漾,通過在聲明時(shí)的數(shù)據(jù)類型后面加一個(gè)感嘆號(hào)(!)來實(shí)現(xiàn):

var str: String! = "Hello World!"
str //Hello World!

可以看到?jīng)]有使用(?)進(jìn)行顯式的折包也得到了Some中的值呐能,這個(gè)語法相當(dāng)于告訴編譯器:在我們使用Optional值前,這個(gè)Optional值就會(huì)被初始化从藤,并且總是會(huì)有值催跪,所以當(dāng)我們使用時(shí),編譯器就幫我做了一次拆包夷野。如果你確信你的變量能保證被正確初始化懊蒸,那就可以這么做,否則還是不要嘗試為好悯搔。
另外:在上面可以看到骑丸,Optional其實(shí)就是一個(gè)枚舉,然后給它指定一個(gè)類型就行了妒貌,所以下面這兩種方法都能聲明一個(gè)Optional值:

var str: String! = "Hello World!"
var str2: Optional<String>

Optional Binding
在說Optional Binding之前通危,我想先說下Xcode6 Beta5在這一版中的一個(gè)小變化:在Xcode6 Beta5之前,如果是一個(gè)Optional值灌曙,可以直接放到條件判斷語句中菊碟,如:

var str: String? = "Hello World!"
if str {
    "not nil"
} else {
    "nil"
}

如果不是nil,則右邊的Playground會(huì)顯示“not nil”在刺;反之則顯示“nil”逆害,但是至Xcode6 Beta5開始,這樣就不能通過編譯器了蚣驼,你需要用下面這種方式來代替:

var str: String? = "Hello World!"
if str != nil {
    "not nil"
} else {
    "nil"
}

看似合理魄幕,但是在某種情況下會(huì)非常不爽難過,比如你在str != nil條件成真后接著在上下文中使用str颖杏,會(huì)被要求進(jìn)行拆包纯陨,我們以一個(gè)Int類型的Optional來做示例:

var count: Int?
count = 100
if count != nil {
    "count is " + String(count!)    //count is 100
} else {
    "nil"
}

我在把count強(qiáng)轉(zhuǎn)成String的時(shí)候被要求拆包了,這是因?yàn)閏ount本身是一個(gè)Optional的類型留储,為了避免在條件判斷語句后執(zhí)行一次或更多次的拆包翼抠,Swift引進(jìn)了Optional Binding,我們就可以這樣做:

var count: Int?
count = 100
if let validCount = count {
    "count is " + String(validCount)    //count is 100
} else {
    "nil"
}

通過在條件判斷語句中(如if获讳、while等)把Optional值直接給一個(gè)臨時(shí)常量机久,Swift會(huì)自動(dòng)檢測(cè)Optional是否包含值,如果包含值赔嚎,會(huì)隱式的拆包并給那個(gè)臨時(shí)常量,在接下來的上下文中就能直接使用這個(gè)臨時(shí)常量了,這樣是不是就覺得很爽呢微笑

注:在Optional Binding中尤误,除了以常量的方式去接收拆包的值之外侠畔,也能以一個(gè)變量的形式
去接收,但相信在大多數(shù)情況下我們只是使用那個(gè)值就行了损晤,并不會(huì)去改變它软棺。

Swift 1.2 新語法:
在if let 中可以使用條件判斷了:

var a: NSString?
a = "test"
if let b = a {
    b
}

if true, let b = a where b == "test" {
    "true"
} 

如果a 不是"test",則不會(huì)打印出"true"尤勋。

Optional Chaining
Optional Chaining對(duì)Swift來說是很基本但又必不可少的東西喘落,相對(duì)于簡(jiǎn)單類型(Int、String等)來說最冰,Optional更主要的應(yīng)用場(chǎng)景是在復(fù)雜對(duì)象上瘦棋,當(dāng)一個(gè)對(duì)象包含另一個(gè)對(duì)象,同時(shí)這兩個(gè)對(duì)象都有可能為nil的情況下才是Optional派上用場(chǎng)的地方暖哨,在Objective-C里赌朋,向nil發(fā)消息得到的就是一個(gè)nil,但是Swift不能在nil上直接調(diào)用方法或?qū)傩云茫瑫r(shí)為了方便我們使用沛慢,從而引入了Optional類型,可是這還不夠达布,我們做一個(gè)簡(jiǎn)單的例子:

class Person {
    var pet: Pet?
}

class Pet {
    var name: String
    
    var favoriteToy: Toy?
    
    init (name: String) {
        self.name = name
    }
}

class Toy {
    var name: String
    
    init (name: String) {
        self.name = name
    }
}

一個(gè)Person對(duì)象代表一個(gè)人团甲,這個(gè)人可能有一個(gè)寵物,寵物會(huì)有它自己的名字黍聂,而且寵物可能會(huì)有自己喜愛的玩具躺苦,按照前面提到的知識(shí),我們要首先判斷這個(gè)人有沒有寵物分冈,然后再判斷他的寵物有沒有喜愛的玩具圾另,然后才能得到這個(gè)玩具的名稱,利用Optional Binding雕沉,我們寫出來的可能就像這樣:

let jackon = Person()
jackon.pet = Pet(name: "Max")
jackon.pet?.favoriteToy = Toy(name: "Ball")
if let pet = jackon.pet {
    if let toy = pet.favoriteToy {
        toy.name
    }
}

這里用到了兩個(gè)if集乔,因?yàn)閜et和toy對(duì)象都可能為nil,我們需要預(yù)防每一個(gè)可能為nil的對(duì)象坡椒,如果這個(gè)對(duì)象再?gòu)?fù)雜一點(diǎn)扰路,那if也就更多了,而使用Optional Chaining的話倔叼,寫出來的就像這樣:

let jackon = Person()
jackon.pet = Pet(name: "Max")
jackon.pet?.favoriteToy = Toy(name: "Ball")
if let toy = jackon.pet?.favoriteToy {
    toy.name
}

當(dāng)一個(gè)Optional值調(diào)用它的另一個(gè)Optional值的時(shí)候汗唱,Optional Chaining就形成了,基本上丈攒,Optional Chaining就是總是返回一個(gè)Optional的值哩罪,只要這個(gè)Chaining中有一個(gè)值為nil授霸,整條Chaining就為nil,和Objective-C的向nil發(fā)消息類似际插。
有一點(diǎn)很有趣碘耳,就是Optional Chaining除了能將屬性返回的類型變?yōu)镺ptional外,連方法的返回值都能強(qiáng)制變?yōu)镺ptional框弛,哪怕這個(gè)方法沒有返回值辛辨,但是別忘了,Void也算是一個(gè)類型:
typealias Void = ()
如果我們的Pet類有一個(gè)玩玩具的play方法的話瑟枫,就可以這樣來判斷是否會(huì)調(diào)用成功:

if let p: Void = jackon.pet?.play() {
    "play is called"
}

使用Optional Chaining斗搞,能使我們的代碼變得更加可讀,同時(shí)更加簡(jiǎn)潔慷妙。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末僻焚,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子景殷,更是在濱河造成了極大的恐慌溅呢,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,548評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件猿挚,死亡現(xiàn)場(chǎng)離奇詭異咐旧,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)绩蜻,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,497評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門铣墨,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人办绝,你說我怎么就攤上這事伊约。” “怎么了孕蝉?”我有些...
    開封第一講書人閱讀 167,990評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵屡律,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我降淮,道長(zhǎng)超埋,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,618評(píng)論 1 296
  • 正文 為了忘掉前任佳鳖,我火速辦了婚禮霍殴,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘系吩。我一直安慰自己来庭,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,618評(píng)論 6 397
  • 文/花漫 我一把揭開白布穿挨。 她就那樣靜靜地躺著月弛,像睡著了一般肴盏。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上尊搬,一...
    開封第一講書人閱讀 52,246評(píng)論 1 308
  • 那天叁鉴,我揣著相機(jī)與錄音,去河邊找鬼佛寿。 笑死,一個(gè)胖子當(dāng)著我的面吹牛但壮,可吹牛的內(nèi)容都是我干的冀泻。 我是一名探鬼主播,決...
    沈念sama閱讀 40,819評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼蜡饵,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼弹渔!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起溯祸,我...
    開封第一講書人閱讀 39,725評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤肢专,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后焦辅,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體博杖,經(jīng)...
    沈念sama閱讀 46,268評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,356評(píng)論 3 340
  • 正文 我和宋清朗相戀三年筷登,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了剃根。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,488評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡前方,死狀恐怖狈醉,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情惠险,我是刑警寧澤苗傅,帶...
    沈念sama閱讀 36,181評(píng)論 5 350
  • 正文 年R本政府宣布,位于F島的核電站班巩,受9級(jí)特大地震影響渣慕,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜趣竣,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,862評(píng)論 3 333
  • 文/蒙蒙 一摇庙、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧遥缕,春花似錦卫袒、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,331評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽宝穗。三九已至,卻和暖如春码秉,著一層夾襖步出監(jiān)牢的瞬間逮矛,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,445評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工转砖, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留须鼎,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,897評(píng)論 3 376
  • 正文 我出身青樓府蔗,卻偏偏與公主長(zhǎng)得像晋控,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子姓赤,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,500評(píng)論 2 359

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