之前學(xué)習(xí) Swift 的時候都是比較破碎西采,零零散散,以至于有些地方學(xué)習(xí)的不夠透徹继控。所以趁最近有時間械馆,就開始重新學(xué)習(xí) Swift ,從最基本的開始學(xué)習(xí)武通,希望能深入理解霹崎,見微知著!
關(guān)于 Swift 我們都是到是類型安全型的冶忱,相較于 OC 尾菇,安全似乎更能體現(xiàn)出來。關(guān)于這一方面囚枪, Swift 的可選型(optional)就不得不說了派诬,可選型可以說是 Swift 最為突出的特性之一】衾可能有的同學(xué)在看 Swift 的過程中會遇到可選型(比如 String?
)千埃,有時也會見到 String!
這樣的,搞不明白其中的意思忆植,所以今天就來一步步理解可選型放可。
一、什么是 Optional
Optional 是 Swift 新加入的類型朝刊,所以學(xué)過 OC 的童鞋就知道在 OC 中是沒有這個概念的耀里。可選型的意思簡單理解是:有值得時候就有值拾氓,無值的時候就是 nil 冯挎。Swift 中的 nil 和其他語言中的 nil 還有些不一樣,nil 自己本身就是一種類型咙鞍,沒有就是 nil 房官,是和其他類型嚴(yán)格區(qū)分開的趾徽。
可選型的定義很簡單:類型 + ? 。比如 String?
翰守、Int?
孵奶、Float?
等,這里需要注意的是 String?
和 String
是完全不同的兩個類型蜡峰,前者是 String
類型的額可選型了袁,后者是 String
類型,注意區(qū)分湿颅。舉個例子载绿,在 OC 中我們可以這樣寫
NSString *name = @"loveway";
name = nil;
上面的這種寫法在 OC 中是沒有問題的,相比于上面油航,在 swift 中
var name: String = "loveway"
name = nil
如果我們像上面代碼中這樣寫就會報錯崭庸,如下
說的是 nil 是不可以分配給 String 類型的,這也說明在 swift 中 nil 是和其他類型嚴(yán)格區(qū)分的劝堪。改為可選型即可冀自,
var name: String? = "loveway"
name = nil
可選型揉稚,顧名思義就是可以選擇秒啦,比如 String?
的意思就是可以在 String
和 nil
之間選擇,可以是 String
也可以是 nil
搀玖。如果一個變量定義成 String
余境,那么這個變量就會是 String
類型,而不可能是nil
灌诅。
還有一點需要注意的是聲明可選型必須是顯示的聲明也就是必須是
var name: String? = nil
這樣芳来,而不能是
var name = nil
這樣,因為 Swift 在做類型判斷的時候無法判斷 name 到底是 String 類型的可選型還是其他類型的可選型猜拾,因此會導(dǎo)致編譯錯誤即舌。
Tips: 當(dāng)然枚舉類型的寫法還可以如
var name: Optional<String> = Optional.Some("Loveway")
這樣,只不過我們一般都用
var name: String? = nil
這樣的簡寫挎袜。
二顽聂、Optional的解包
可選型是不能夠被直接使用的(因為 Swift 是類型安全的,可選型的值又可能會是 nil盯仪,如果不做處理可能導(dǎo)致程序 crash)紊搪,如果我們想使用可選型的值,那么在這之前我們需要做的一項工作就是:解包(unwarp)全景!
- 1耀石、強制解包
所謂的強制解包意思就是我知道這個類型是可選型,但是在我的程序執(zhí)行到這里的時候我可以保證它是有值得爸黄,所以我要在這里使用它滞伟。具體表現(xiàn)形式就是在可選型后面加個!
揭鳞,如下
var name: String? = "loveway"
"My name is " + name!
但是這樣的解包是不安全,因為你不知道什么時候你的這個可選型就會變成 nil梆奈,如果我們代碼非常多的話汹桦,一不小心為 nil了,可能會導(dǎo)致程序崩潰鉴裹。這個時候我們會想到一種方法:判空舞骆!如下,
var name: String? = "loveway"
if name != nil {
"My name is " + name!
} else {
print("name is nil")
}
這樣寫似乎是沒有什么問題了径荔,但是需要注意的是督禽,你在判斷非 nil 的作用域內(nèi)使用 name 的時候還必須把 !
帶上,這樣代碼比較多的時候還是比較麻煩总处。于是我們可以使用下面這種方式狈惫,
- 2、使用
if let
解包
使用if let
解包如下鹦马,
var name: String? = "loveway"
if let name = name {
"My name is " + name
} else {
print("name is nil")
}
這種解包方式可以保證 name 是解包過的胧谈,不會再是 nil 這種情況,其實邏輯是和上面做非空判斷一樣的荸频。當(dāng)然你把 let
換成 var
也是可以的菱肖,效果是一樣的,只不過我們一般要用的是解包后的值旭从,而不會去改變它稳强,所以平常使用中一般都是用 if let
。
同時 if let
可以同時一次性解包多個可選型和悦,用 ,
隔開退疫,使語句簡潔,如下
var name: String? = "loveway"
var age: Int? = 18
if let name = name, age = age {
"My name is " + name
} else {
print("name is nil")
}
最后鸽素,既然這里使用的是 if
褒繁,那么同樣我們可以如下這樣用,來進行進一步的判斷篩選
var name: String? = "loveway"
var age: Int? = 18
if let name = name, age = age where age == 18 {
print("My name is \(name), age is \(String(age))")
} else {
print("name is nil")
}
如上也是可以的馍忽。
三棒坏、可選鏈?zhǔn)秸{(diào)用(Optional Chaining)
可選鏈?zhǔn)秸{(diào)用(Optional Chaining)是一種可以在當(dāng)前值可能為 nil 的可選值上請求和調(diào)用屬性、方法及下標(biāo)的方法舵匾。如果可選值有值俊抵,那么調(diào)用就會成功,如果可選值是 nil 坐梯,那么調(diào)用將返回 nil徽诲。多個調(diào)用可以連接在一起形成一個調(diào)用鏈,如果其中任何一個節(jié)點為 nil ,整個調(diào)用鏈都會失敗谎替,即返回 nil 偷溺。
下面我們就來舉個例子具體說明可選鏈,如下
var name: String? = "loveway"
if let name = name {
print(name.uppercaseString)
} else {
print("name is nil")
}
我們來解包 name 钱贯,如果有值就打印出 name 的大寫挫掏,如果沒有就輸出 name is nil
,其實上面這段代碼完全等同于
var name: String? = "loveway"
name?.uppercaseString
上面這句代碼的意思就是如果可選型變量 name 有值秩命,那么就對 name 進行解包尉共,并得到 name 的uppercaseString 值,如果沒有弃锐,那么這句代碼就會返回一個 nil 袄友。這樣就符合 Swift 的類型安全,完全是沒有問題的霹菊。但是如果你寫成
var name: String? = "loveway"
name!.uppercaseString
也是可以的剧蚣,不過不安全,因為如果 name 沒有值旋廷,你進行強制解包鸠按,就會報錯。
所以我們以后可能會用到類似于 person?.name?.uppercaseString
這樣的一層層解包的饶碘,這種就是可選鏈目尖。
四、Nil Coalescing Operator(空合運算符)
如上熊镣,如果我們想把解包后的值存起來的話卑雁,可以這樣
let newName = name == nil ? "no name" : name!
上面代碼的意思就是如果 name 為 nil 募书,newName 就是 "no name"绪囱,否則 newName 就是 name!(name的解包)。其實 Swift 為我們提供了更簡潔的語法莹捡,如下
let newName2 = name ?? "no name"
上面代碼的意思就是 name 如果有值 newName2 的值就是 name! ,否則就是 no name 鬼吵。這里需要注意的是 ??
是空合運算符,這樣寫的可閱讀性強篮赢,比較簡潔齿椅。
當(dāng)然關(guān)于 ??
遠不止這些,有興趣的同學(xué)可以看 聊聊swift語言中的“??” 這篇文章启泣。
五涣脚、隱式可選型
上面我們都知道了,創(chuàng)建一個顯示可選型是: 類型 + ?
寥茫。這里創(chuàng)建隱式可選型的就是: 類型 + !
遣蚀。
var name: String! = "loveway"
這里可能有的童鞋會疑惑,已經(jīng)有了顯示的可選型,為什么還需要有隱式的可選型芭梯。這里其實隱式的可選型也是有一定作用的险耀。比如你有一個變量,聲明為隱式的可選型(!
)玖喘,它的作用就是甩牺,當(dāng)你這個類沒有被初始化的時候他是沒有值的,但是當(dāng)你這個類初始化以后累奈,你可以確保他是有值的贬派,所以這里聲明為隱式的可選型,而不是顯示的澎媒。同樣需要注意的是隱式的可選型也是可選型赠群,如果你需要用它的值,你也是要進行判斷的旱幼。如果不進行判斷而直接使用查描,可能會造成不可預(yù)料的后果!
差不多可選型就到這里了柏卤,如果還有什么遺漏冬三,歡迎大家指正!