Swift中的問號?和感嘆號!

Overview

在 C 和 Objective-C 中稽莉,沒有可選項(xiàng)的概念炬称。在 Objective-C 中有一個近似的特性柜砾,一個方法可以返回一個對象或者返回 nil 稳其。 nil 的意思是“缺少一個可用對象”。然而耕驰,他只能用在對象上爷辱,卻不能作用在結(jié)構(gòu)體,基礎(chǔ)的 C 類型和枚舉值上耍属。對于這些類型托嚣,Objective-C 會返回一個特殊的值(例如 NSNotFound )來表示值的缺失巩检。這種方法是建立在假設(shè)調(diào)用者知道這個特殊的值并記得去檢查他厚骗。然而,Swift 中的可選項(xiàng)就可以讓你知道任何類型的值的缺失兢哭,他并不需要一個特殊的值领舰,它強(qiáng)調(diào)的是有沒有,而非空不空迟螺。

可以利用可選項(xiàng)來處理值可能缺失的情況冲秽。可選項(xiàng)意味著:

  • 這里有一個值矩父,他等于x
    或者
  • 這里根本沒有值

swift里面常量/變量的聲明方式:

聲明常量 let 聲明變量 var
1??let name = "swift"let name: String = "swift" 6??var name = "swift"var name: String = "swift"
2??let name: String 7??var name: String
3??let name: String?(或!) = "swift" 8??var name: String?(或!) = "swift"
4??let name: String? 9??var name: String?
5??let name: String! ??var name: String!

普通類型

常量/變量聲明的時候類型后面不帶有?或者!為普通類型锉桑,也就是上表中1??,2??窍株,6??民轴,7??聲明方式

  • 要么在聲明的時候賦初始值攻柠,要么在其所屬類的初始化方法中賦初始值,才能參與運(yùn)算
  • 這種類型沒有默認(rèn)初始值后裸,且生命周期中不能接收nil

可選項(xiàng)(Optional Type)

常量/變量聲明的時候類型后面帶有?或者!為可選類型(optional type瑰钮,即可選項(xiàng)),也就是上表中3??微驶,4??浪谴,5??,8??因苹,9??苟耻,??聲明方式。
此外let name: Optinal<String> 的簡寫形式是4??容燕,二者作用跟和用法是完全一樣的梁呈; 同理let name: ImplicitlyUnwrappedOptional<String>的簡寫形式是5??,二者作用跟和用法也是完全一樣蘸秘。

  • 聲明為Optional常量時如果沒有賦初始值官卡,此常量沒有默認(rèn)值,需要在構(gòu)造函數(shù)中給常量設(shè)置初始數(shù)值
  • 聲明為Optional的變量醋虏,如果不顯式的賦值就會有個默認(rèn)值nil
  • 聲明為Optional的變量/常量不能直接參與運(yùn)算寻咒,必須解包后才能參與運(yùn)算
  • 解包后的Optional變量/常量如果沒有值(為nil)參與運(yùn)算也會發(fā)生Crash

我們可以對一個可選項(xiàng)類型(Optional Type)使用后綴操作符!來強(qiáng)制拆包(force unwrap)訪問這個值,來繼續(xù)后面的操作颈嚼。
可選類型類似于Objective-C中指針的nil值毛秘,但是nil只對類(class)有用,而swift中可選類型對所有的類型都可用阻课,并且更安全叫挟。

強(qiáng)制展開

如果一個可選有值,它“不等于” nil 限煞,可以通過比較 nil 來判斷一個可選中是否包含值抹恳。

一旦你確定可選中包含值,可以使用后綴操作符!來強(qiáng)制拆包(force unwrap)訪問這個值署驻,奋献,感嘆號的意思就是說“我知道這個可選項(xiàng)里邊有值,展開吧旺上∑柯欤”這就是所謂的可選值的強(qiáng)制展開。

var myString:String?
myString = "Hello, Swift!"

if myString != nil {
   print(myString)  //prints:Optional("Hello, Swift!")
   // 強(qiáng)制展開
   print(myString!)  //prints:Hello, Swift!
}else{
   print("myString 值為 nil")
}

注意:
使用 ! 來獲取一個不存在的可選值會導(dǎo)致carsh宣吱,在使用!強(qiáng)制展開之前必須確鼻哉猓可選項(xiàng)中包含一個非 nil 的值。

可選項(xiàng)綁定

可以使用可選項(xiàng)綁定來判斷可選項(xiàng)是否包含值征候,如果包含就把值賦給一個臨時的常量/變量杭攻∪魇裕可選綁定可以與 if 和 while 的語句使用來檢查可選項(xiàng)內(nèi)部的值,并賦值給一個變量或常量朴上。

var myString:String?
myString = "Hello, Swift!"

if let yourString = myString {
   print("你的字符串值為 - \(yourString)")
}else{
   print("你的字符串沒有值")
}
//prints:你的字符串值為 - Hello, Swift!

隱式展開

有時在一些程序結(jié)構(gòu)中可選項(xiàng)一旦被設(shè)定值之后垒棋,就會一直擁有值。在這種情況下痪宰,就可以去掉檢查的需求叼架,不必每次訪問的時候都進(jìn)行展開,因?yàn)樗梢园踩拇_認(rèn)每次訪問的時候都有一個值衣撬。這種類型的可選項(xiàng)被定義為隱式展開可選項(xiàng)乖订。

通過在類型后邊添加一個嘆號( String! )而非問號( String? ) 來聲明一個隱式展開可選項(xiàng)。

在可選項(xiàng)被定義的時候就能立即確認(rèn)其中有值的情況下具练,隱式展開可選項(xiàng)非常有用乍构,主要被用在 Swift 類的初始化過程中。

下面的栗子展示了在訪問被明確為 String 的可選項(xiàng)展開值時扛点,可選字符串和隱式展開可選字符串的行為區(qū)別:

let possibleString: String? = "An optional string."
let forcedString: String = possibleString! // requires an exclamation mark
 
let assumedString: String! = "An implicitly unwrapped optional string."
let implicitString: String = assumedString // no need for an exclamation mark

你可以把隱式展開可選項(xiàng)當(dāng)做在每次訪問它的時候被給予了自動進(jìn)行展開的權(quán)限(編譯器自動在操作前補(bǔ)上一個!進(jìn)行拆包哥遮,然后在執(zhí)行后面的操作,當(dāng)然如果該值是nil陵究,也一樣會報(bào)錯crash掉)眠饮,這樣就可以在聲明可選項(xiàng)的時候添加一個嘆號而不是每次調(diào)用的時候在可選項(xiàng)后邊添加一個嘆號。

你可以像對待普通可選一樣對待隱式展開可選項(xiàng)來檢查里邊是否包含一個值:

if assumedString != nil {
    print(assumedString)
}
// prints "An implicitly unwrapped optional string."

你也可以對待隱式展開可選項(xiàng)通過可選項(xiàng)綁定在一句話中檢查和展開值:

if let definiteString = assumedString {
    print(definiteString)
}
// prints "An implicitly unwrapped optional string."

合并空值運(yùn)算符

上面對可選類型的三種處理不是需要繁瑣的判斷就是存在Crash風(fēng)險不夠安全铜邮,那么??的出現(xiàn)很好的解決了這個問題仪召。

合并空值運(yùn)算符 (a ?? b )如果可選項(xiàng) a 有值則展開,如果沒有值松蒜,是 nil 扔茅,則返回默認(rèn)值 b 。表達(dá)式 a 必須是一個可選類型秸苗。表達(dá)式 b 必須與 a 的儲存類型相同召娜。

合并空值運(yùn)算符是下邊代碼的縮寫:a != nil ? a! : b

let defaultColorName = "red"
var userDefinedColorName: String? // defaults to nil
var colorNameToUse = userDefinedColorName ?? defaultColorName
// userDefinedColorName is nil, so colorNameToUse is set to the default of "red"
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市难述,隨后出現(xiàn)的幾起案子萤晴,更是在濱河造成了極大的恐慌吐句,老刑警劉巖胁后,帶你破解...
    沈念sama閱讀 218,682評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異嗦枢,居然都是意外死亡攀芯,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評論 3 395
  • 文/潘曉璐 我一進(jìn)店門文虏,熙熙樓的掌柜王于貴愁眉苦臉地迎上來侣诺,“玉大人殖演,你說我怎么就攤上這事∧暝В” “怎么了趴久?”我有些...
    開封第一講書人閱讀 165,083評論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長搔确。 經(jīng)常有香客問我彼棍,道長,這世上最難降的妖魔是什么膳算? 我笑而不...
    開封第一講書人閱讀 58,763評論 1 295
  • 正文 為了忘掉前任座硕,我火速辦了婚禮,結(jié)果婚禮上涕蜂,老公的妹妹穿的比我還像新娘华匾。我一直安慰自己,他們只是感情好机隙,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,785評論 6 392
  • 文/花漫 我一把揭開白布蜘拉。 她就那樣靜靜地躺著,像睡著了一般有鹿。 火紅的嫁衣襯著肌膚如雪诸尽。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,624評論 1 305
  • 那天印颤,我揣著相機(jī)與錄音您机,去河邊找鬼。 笑死年局,一個胖子當(dāng)著我的面吹牛际看,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播矢否,決...
    沈念sama閱讀 40,358評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼仲闽,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了僵朗?” 一聲冷哼從身側(cè)響起赖欣,我...
    開封第一講書人閱讀 39,261評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎验庙,沒想到半個月后顶吮,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,722評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡粪薛,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年悴了,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,030評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡湃交,死狀恐怖熟空,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情搞莺,我是刑警寧澤息罗,帶...
    沈念sama閱讀 35,737評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站才沧,受9級特大地震影響阱当,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜糜工,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,360評論 3 330
  • 文/蒙蒙 一弊添、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧捌木,春花似錦油坝、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至帆啃,卻和暖如春瞬女,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背努潘。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評論 1 270
  • 我被黑心中介騙來泰國打工诽偷, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人疯坤。 一個月前我還...
    沈念sama閱讀 48,237評論 3 371
  • 正文 我出身青樓报慕,卻偏偏與公主長得像,于是被迫代替她去往敵國和親压怠。 傳聞我的和親對象是個殘疾皇子眠冈,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,976評論 2 355

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