一惩琉、類型定義
在 OC 中哮独,我們可以這樣定義一個變量:
int a = 0;
也可以這樣定義:
int a;
這兩種定義的方式都是一樣的,這里的 一樣 是指 值 是一樣的洼滚。第二種方式雖然沒有顯式的指定其值埂息,但是會默認(rèn)設(shè)置一個 0。
如果在開發(fā)的過程中,我們一定要對這兩種情況做區(qū)分千康,應(yīng)該怎么處理呢享幽?畢竟沒有賦值與默認(rèn)設(shè)置一個初始值,還是有所區(qū)別的拾弃。在 OC 中沒有專門的語法支持值桩,當(dāng)然也是能實現(xiàn)的,只是需要額外的變量來做輔助豪椿,特別的麻煩奔坟。
在 OC 中不行,但是在 Swift 中就顯得小菜一碟了搭盾。多了一種 可選 類型咳秉。什么叫可選類型呢?
一個變量沒有默認(rèn)值這一說鸯隅,要么有值澜建,要么沒有值。 這就叫做可選類型蝌以。
提示:
Swift 中的可選類型炕舵,是一種單獨的數(shù)據(jù)類型。有可選類型饼灿,那么就有非可選類型幕侠。
定義有如下三種方式:
var a:Optional<Int>
var b:Int?
var c:Int!
以上的 a帝美,b碍彭,c 都是可選類型。
但是這兩三種定義的方式悼潭,也是有異同的庇忌,后面再做介紹。
二舰褪、如何標(biāo)識有值與妹紙
上面說了皆疹,可選類型的變量,主要針對的是有值還是沒有值占拍,兩種狀態(tài)略就。那么如何來標(biāo)識呢?
首先來認(rèn)識一下 OC 中的 nil晃酒。代表的是一個空指針表牢,或者是默認(rèn)指針的值,或者是手動賦值為 nil贝次〈扌耍總之,給一個指針賦值為 nil, 代表的是一個空值敲茄,是一個具體的空值位谋。
但是在 Swift 中就不一樣了。只能給一個可選類型的變量賦值為 nil堰燎,一旦賦值為 nil掏父,那么就代表是當(dāng)前可選類型的變量就為沒有值的狀態(tài)。這里有點繞秆剪,并不是說當(dāng)前的變量為 nil损同,而是一種狀態(tài)而已。換句話說鸟款,當(dāng)給一個可選類型賦值為nil的時候膏燃,并不是將 nil給當(dāng)前的變量,而是將當(dāng)前的變量變成一個 沒有值 的狀態(tài)何什。
同時也要注意這里強(qiáng)調(diào)的是可選類型组哩,沒有說指針。所以可選類型可以是基本數(shù)據(jù)類型处渣,也可以是所謂的指針伶贰。
接著上面的定義:
var a:Optional<Int>
var b:Int?
var c:Int!
以上的三個都是可選類型的變量。在定義可選類型的時候罐栈,不給賦值黍衙,那么當(dāng)前的可選類型的變量就屬于沒有值的狀態(tài)。那么問題來了荠诬,那他到底是什么值呢琅翻?
答案是 沒有值 的狀態(tài),說明當(dāng)前變量屬于一個沒有值的狀態(tài)柑贞。
說了半天的可選類型方椎,那么非可選類型的又是怎么樣的呢?
var b:Int
上面這句代碼钧嘶,在 Swift 中是不能通過的棠众。因為這是一個非可選類型的變量,非可選類型的變量有决,每時每刻都必需要保證有值闸拿。比如這樣的:
接下來看一個變量的有值與沒有值之間的轉(zhuǎn)換:
// 定義一個可選類型的變量
// 當(dāng)前的 e, 是沒有值的狀態(tài)
var e:Int?
// 當(dāng)前的 e, 是有值的狀態(tài)
e = 3
// 當(dāng)前的 e, 變成了一個沒有值的狀態(tài)
e = nil
三、獲取可選類型的值
3.1 獲取可選類型的值(上)
可選類型书幕,是一個單獨的數(shù)據(jù)類型新荤。對于賦值來說,與我們熟悉的賦值沒有任何區(qū)別按咒,是一個 Int 類型的值迟隅,直接給一個數(shù)字就可以了但骨,其它類型的類似。但是取值智袭,就有點不一樣了奔缠。
看一下下面的打印結(jié)果:
可以看出,實際的值被一個 Optional 包起來了吼野。再來看一下這個:
直接報錯了校哎,說明可選類型的是不能直接使用的。那應(yīng)該如何去獲取呢瞳步?
在上圖的報錯中闷哆, 就已經(jīng)有提示了,正確的獲取方式是:
print(e! + 3)
一般在 可選類型的后面加一個 单起! 就可以了抱怔。但是這只是其中的一種情況,具體的放在后面介紹嘀倒。在上面也介紹了屈留,可選類型是一種獨立的類型,只是每種可選類型肯定是對應(yīng)著某種特定的數(shù)據(jù)類型测蘑。我們對可選類型的取值灌危,主要的目的就是獲取當(dāng)前可選類型中的特定數(shù)據(jù)類型的值。
3.2 獲取可選類型的值(下)
上面簡單的介紹了碳胳。對于一個可選類型變量的取值勇蝙,是需要做一些處理的,不能直接獲取挨约。接下來的問題是:
對于可選類型變量的取值味混,應(yīng)該注意些什么呢?
說明烫罩,對于一個可選類型的變量來說惜傲,如果當(dāng)前的變量為 沒有值 的狀態(tài),還去獲取值的話贝攒,這是不允許的,直接報錯时甚。
3.3 獲取可選類型的值(終)
從上面的分析可以得出隘弊,獲取可選類型的值,一定要保證當(dāng)前可選類型變量處于有值的狀態(tài)荒适,否則直接報錯梨熙。細(xì)心想想也對,盡然當(dāng)前的變量的狀態(tài)就是一個沒有值的狀態(tài)了刀诬,你還要去取值咽扇,這不是找死么?
那么問題又來了: 我們應(yīng)該如何去獲取可選類型的值呢? 關(guān)于這個問題,我們主要是圍繞著 只會在有值的狀態(tài)下质欲,才去解包取值树埠。
3.3.1 if 取值法
// if 取值法
if e != nil {
print(e! + 3)
}
意思就是先判斷 e 是否不為 nil, 如果不為 nil, 那么就強(qiáng)制解包取值嘶伟。
3.3.2 綁定取值
// 綁定取值
if let e_value = e {
print(e_value + 3)
}
這種方式比第一種方式方便了很多怎憋,直接通過 if 判斷當(dāng)前的 e 是否有值,如果有值,則直接強(qiáng)制解包為 e_value, 如果沒有值僧界,那么當(dāng)前的 if 條件不成立艾恼。
3.3.3 guard取值
// 函數(shù)
func hgFunc(e:Int?) {
guard let e_guard_value = e else {
print("e 當(dāng)前沒有值")
return
}
print(e_guard_value)
}
函數(shù) hgFunc 中的參數(shù)是一個可選類型,所以在使用的的時候可定需要做判斷荸镊。但是這個 guard 與 if 很相似,同時也還有很大的不同。仔細(xì)觀察會發(fā)現(xiàn)规个,括號中執(zhí)行的條件是 為 false 的情況下才會執(zhí)行。還有一個更明顯的特點是 e_guard_value 這個變量姓建,在 e_guard_value的括號外面還能有效诞仓。如果使用 if 的話,還需要額外的聲明一個變量速兔。
3.3.4 雙問號取值
// 如果 e 有值, 則獲取 e 中的值
// 沒有值, 則賦值為5
let e_value = e ?? 5
// 所以 e_value 值要么是 e 中的值
// 要么是 5
print(e_value)
這種方式也比較的直觀墅拭,能很好的處理一些一定要保證能獲取一個有效值的情況。
四涣狗、說在后面的話
是的谍婉,對于可選類型,我暫時就理解到這里了镀钓。在 Swift 開發(fā)中穗熬,使用得最多的即使可選類型的變量,所以理解好可選類型是很關(guān)鍵的一步丁溅。當(dāng)然唤蔗,主要是理解好,并在不同的場景使用好才是最關(guān)鍵的窟赏。