在本文中,您將學(xué)習(xí)可選,其用例以及Swift中的可選處理。
在上一篇文章中,我們了解了Swift中可用的不同數(shù)據(jù)類型,并且還注意到這些類型聲明的變量或常量包含默認(rèn)值。
例:
let someValue = Int() print(someValue)
運(yùn)行該程序時(shí),輸出為:
0
但是,Swift中還有另一種稱為 Optional 的數(shù)據(jù)類型,其默認(rèn)值為空值(nil)。如果希望變量或常量中不包含任何值,則可以使用 Optional??蛇x類型可以包含一個(gè)值或不存在一個(gè)值(空值)。
從技術(shù)上講,您可以認(rèn)為它是可選的鞋盒。鞋盒中可能裝有鞋,也可能沒有。因此,從包裝箱中取出鞋子時(shí),您應(yīng)該事先知道。
您可以通過(guò)追加將數(shù)據(jù)類型簡(jiǎn)單地表示為 Optional。 方法是類型附加! 或 ?。 如果可選變量中包含一個(gè)值,則將其值返回為 Optional <Value>,否則返回nil。
var someValue:Int? var someAnotherValue:Int! print(someValue) print(someAnotherValue)
運(yùn)行該程序時(shí),輸出為:
nil nil
在上面的程序中,我們使用 ? 和 ! 初始化了一個(gè)可選類型。兩種方法都可以創(chuàng)建可選的方法,但是有一個(gè)主要的不同,我們將在下面進(jìn)行探討。
聲明一個(gè)可選的 Int 意味著該變量將具有整數(shù)值或無(wú)值。由于沒有為變量分配任何值,因此您可以在屏幕上看到兩個(gè)print語(yǔ)句輸出nil。
let someValue:Int? = 5 print(someValue) print(someValue!)
運(yùn)行該程序時(shí),輸出為:
Optional(5) 5
在上面的程序中,我們聲明了一個(gè)可選Int類型,并在其中分配了值5。
將可選打印為print(someValue)不會(huì)給您返回5,而是為Optional(5)。 它具有如上所述的形式:Optional <Value>。 為了從中訪問(wèn)<Value>,我們需要一種稱為解包(unwrapping)的機(jī)制。
您可以通過(guò)在變量/常量的末尾附加字符 ! 來(lái)展開可選內(nèi)容,如下一行所示 print(someValue!)。print(someValue!) 解開可選內(nèi)容并在屏幕上輸出 5。
但是,請(qǐng)記住,僅當(dāng)確定在訪問(wèn)可選選項(xiàng)時(shí)肯定具有值時(shí),才應(yīng)使用這種解包機(jī)制。
您還可以通過(guò)以下方式創(chuàng)建解包后的可選內(nèi)容:
let someValue:Int! = 5 print(someValue)
運(yùn)行該程序時(shí),輸出為:
5
在上面的程序中,Int! 創(chuàng)建一個(gè)未包裝的可選內(nèi)容,當(dāng)您訪問(wèn)它時(shí),它會(huì)自動(dòng)解包該值,因此您不必每次都!字符。
請(qǐng)確保在使用這些可選選項(xiàng)時(shí),變量在訪問(wèn)時(shí)始終需要有一個(gè)值。如果不這樣做,將會(huì)導(dǎo)致致命的錯(cuò)誤崩潰。
var someValue:Int! var unwrappedValue:Int = someValue //crashes due to this line
當(dāng)您運(yùn)行該程序時(shí),您將得到致命錯(cuò)誤的崩潰:解開Optional值時(shí)意外發(fā)現(xiàn)nil,因?yàn)榇aunwrappedValue:Int = someValue試圖將Optional someValue中的值分配給變量unwrappedValue。
但是,somevalue 是一個(gè)包含 nil 值的可選類型。試圖將 nil 值分配給變量 unwrappedValue (這不是一個(gè)Optional)將導(dǎo)致崩潰。
下面將說(shuō)明處理此情況的不同方法。
為了使用可選值,需要將其解包。使用可選值的更好方法是通過(guò)條件解包,而不是使用 ! 運(yùn)算符強(qiáng)制解包。
這是因?yàn)橛袟l件的展開詢問(wèn)是否檢查此變量是否有值?。如果是,請(qǐng)?zhí)峁┰撝担駝t將處理nil情況。
相反,強(qiáng)制展開表示此變量在使用時(shí)確實(shí)具有一個(gè)值。 因此,當(dāng)您強(qiáng)制解開一個(gè)nil的變量時(shí),您的程序?qū)⒃诮忾_一個(gè)可選異常并崩潰時(shí)拋出意外發(fā)現(xiàn)的nil。下面說(shuō)明了一些用于條件展開的技巧:
您可以使用if語(yǔ)句,然后將可選參數(shù)與nil進(jìn)行比較,以找出可選參數(shù)是否包含值。您可以在if語(yǔ)句中使用比較運(yùn)算符“等于”運(yùn)算符(==)或“不等于”運(yùn)算符(!=)。
var someValue:Int? var someAnotherValue:Int! = 0 if someValue != nil { print("包含值 \(someValue!)") } else { print("不包含值") } if someAnotherValue != nil { print("包含值 \(someAnotherValue!)") } else { print("不包含值") }
運(yùn)行該程序時(shí),輸出為:
不包含值 包含值 0
在上面的程序中,如果可選語(yǔ)句包含值,則執(zhí)行if語(yǔ)句內(nèi)的代碼,否則執(zhí)行else塊內(nèi)的語(yǔ)句。使用此方法進(jìn)行可選處理的主要缺點(diǎn)是,您仍然需要從可選中使用 ! 運(yùn)算符解包該值。
可選綁定可幫助您找出可選值是否包含值。如果可選值包含一個(gè)值,則該值可用作臨時(shí)常量或變量。因此,可以將可選綁定與if語(yǔ)句一起使用,以檢查可選內(nèi)部的值,并在單個(gè)操作中將其提取為常量或變量。
var someValue:Int? var someAnotherValue:Int! = 0 if let temp = someValue { print("包含值 \(temp)") } else { print("不包含值") } if let temp = someAnotherValue { print("包含值 \(temp)") } else { print("不包含值") }
運(yùn)行該程序時(shí),輸出為:
不包含值 包含值 0
在上面的程序中,如果可選語(yǔ)句包含一個(gè)值,則執(zhí)行if語(yǔ)句中的代碼。否則,else塊將被執(zhí)行。if-let語(yǔ)句還自動(dòng)解開該值,并將解開后的值存儲(chǔ)在temp常量中。該方法的主要優(yōu)勢(shì)在于,盡管可以確定某個(gè)可選內(nèi)容包含一個(gè)值,但您無(wú)需強(qiáng)行解開該值。
您也可以在Swift中使用 guard 語(yǔ)句 處理可選內(nèi)容。如果您不知道什么是 guard,請(qǐng)不要擔(dān)心?,F(xiàn)在,僅將guard視為if-else沒有if阻止的條件。如果條件失敗,則執(zhí)行else語(yǔ)句。如果不是,則執(zhí)行下一條語(yǔ)句。有關(guān)更多詳細(xì)信息,請(qǐng)參見Swift Guard。
func testFunction() { let someValue:Int? = 5 guard let temp = someValue else { return } print("It has some value \(temp)") } testFunction()
運(yùn)行該程序時(shí),輸出為:
It has some value 5
在上面的程序中,guard 包含一個(gè)條件,即可選的 someValue 是否包含一個(gè)值。如果它包含一個(gè)值,那么 guard-let 語(yǔ)句將自動(dòng)解包該值并將解包的值放置在 temp 常量中。否則,else 塊將被執(zhí)行,并且它將返回到調(diào)用函數(shù)。因?yàn)榭蛇x項(xiàng)包含一個(gè)值,所以調(diào)用 print 函數(shù)。更多細(xì)節(jié)請(qǐng)參見Swift guard。
在Swift中,您還可以使用空合運(yùn)算符運(yùn)算符檢查可選項(xiàng)是否包含值。 它被定義為(a??b)。 它展開一個(gè)可選的a,如果它包含一個(gè)值,則返回它,或者如果a為空,則返回默認(rèn)值b。
var someValue:Int! let defaultValue = 5 let unwrappedValue:Int = someValue ?? defaultValue print(unwrappedValue)
運(yùn)行該程序時(shí),輸出為:
5
在上面的程序中,變量someValue定義為可選,并且包含nil值。 空合運(yùn)算符無(wú)法解開可選值,因此返回defaultValue。 因此,語(yǔ)句print(unwrappedValue)在控制臺(tái)中輸出5。
var someValue:Int? = 10 let defaultValue = 5 let unwrappedValue:Int = someValue ?? defaultValue print(unwrappedValue)
運(yùn)行該程序時(shí),輸出為:
10
但是,在上述程序中,可選變量someValue被初始化為值10。因此,空合運(yùn)算符成功地從中解包了該值someValue。因此,該語(yǔ)句在控制臺(tái)臺(tái)中someValue ?? defaultValue返回10,語(yǔ)句print(unwrappedValue)輸出10。