在值可能不存在的情況下,您可以使用可選值栗弟。 可選表示兩種可能性:有一個值,您可以解開可選值以訪問該值工闺,或者根本沒有值乍赫。
這里有一個例子說明如何使用可選項來處理缺少值。 Swift的Int類型有一個初始化器陆蟆,它試圖將String值轉(zhuǎn)換為Int值雷厂。 但是,不是每個字符串都可以轉(zhuǎn)換為整數(shù)叠殷。 字符串“123”可以轉(zhuǎn)換為數(shù)字值123改鲫,但是字符串“hello,world”沒有一個明顯的數(shù)值要轉(zhuǎn)換林束。
let possibleNumber = "123"
let convertedNumber = Int(possibleNumber)
// convertedNumber is inferred to be of type "Int?", or "optional Int"
因為初始化程序可能失敗像棘,它返回一個可選的Int,而不是一個Int壶冒。 可選的Int被寫為Int ?,而不是Int缕题。 問號表示它包含的值是可選的,這意味著它可能包含一些Int值胖腾,或者它可能不包含任何值避除。 (它不能包含任何其他的,如Bool值或String值胸嘁,它是一個Int,或者它根本不是凉逛。
您通過為可選變量賦值特殊值nil將其設(shè)置為無價值狀態(tài):
var serverResponseCode: Int? = 404
// serverResponseCode contains an actual Int value of 404
serverResponseCode = nil
// serverResponseCode now contains no value
nil不能與非可選常量和變量一起使用性宏。 如果代碼中的常量或變量需要在某些條件下缺少某個值,請將其聲明為適當(dāng)類型的可選值状飞。
如果您定義一個可選變量而不提供默認(rèn)值毫胜,則變量將自動設(shè)置為nil:
var surveyAnswer: String?
// surveyAnswer is automatically set to nil
注意:Swift的nil與Objective-C中的nil不一樣。 在Objective-C中诬辈,nil是一個指向不存在的對象的指針酵使。 在Swift中,nil不是一個指針 - 它是一個類型的值的缺失焙糟。 任何類型的可選項都可以設(shè)置為nil口渔,而不僅僅是對象類型。
if語句和強(qiáng)制解包
您可以使用if語句通過將可選項與nil進(jìn)行比較來確定可選項是否包含值穿撮。 您可以使用“等于”運(yùn)算符(==)或“不等于”運(yùn)算符(缺脉!=)執(zhí)行此比較痪欲。
如果一個可選項有一個值,它被認(rèn)為是“不等于”nil:
if convertedNumber != nil {
print("convertedNumber contains some integer value.")
}
// Prints "convertedNumber contains some integer value."
一旦確定可選項包含一個值攻礼,就可以通過在可選項名稱的末尾添加一個感嘆號(R堤摺)來訪問其底層值。 這被稱為強(qiáng)制解開可選值的值(強(qiáng)制解包):
if convertedNumber != nil {
print("convertedNumber has an integer value of \(convertedNumber!).")
}
// Prints "convertedNumber has an integer value of 123."
可選綁定
您可以使用可選綁定來確定一個可選的是否包含一個值礁扮,如果包含知举,則使該值作為臨時常量或變量。 可選綁定可以與if和while語句一起使用太伊,以檢查可選內(nèi)部中的值雇锡,并將該值提取為常量或變量,作為單個操作的一部分倦畅。
為if語句編寫可選綁定遮糖,如下所示:
let possibleNumber = "123"
if let actualNumber = Int(possibleNumber) {
print("\"\(possibleNumber)\" has an integer value of \(actualNumber)")
} else {
print("\"\(possibleNumber)\" could not be converted to an integer")
}
// Prints ""123" has an integer value of 123"
這段代碼的意思是:“如果Int(possibleNumber)返回的可選Int包含一個值,請將一個名為actualNumber的新常量設(shè)置為可選值中包含的值叠赐。
- 如果轉(zhuǎn)換成功欲账,actualNumber常量可以在if語句的第一個分支中使用。 它已經(jīng)被包含在可選內(nèi)容中的值初始化芭概,因此沒有必要使用赛不! 后綴來訪問它的值。 在此示例中罢洲,actualNumber僅用于打印轉(zhuǎn)換的結(jié)果踢故。
- 您可以使用常量和變量與可選綁定。 如果你想在if語句的第一個分支中操作actualNumber的值惹苗,你可以改寫var actualNumber殿较,并且可選內(nèi)容中包含的值將作為變量而不是常量。
您可以根據(jù)需要在單個if語句中包含盡可能多的可選綁定和布爾條件桩蓉,并以逗號分隔淋纲。 如果可選綁定中的任何值為nil或任何布爾條件求值為false,則整個if語句的條件被視為false院究。 以下if語句是等效的:
if let firstNumber = Int("4"), let secondNumber = Int("42"), firstNumber < secondNumber && secondNumber < 100 {
print("\(firstNumber) < \(secondNumber) < 100")
}
// Prints "4 < 42 < 100"
if let firstNumber = Int("4") {
if let secondNumber = Int("42") {
if firstNumber < secondNumber && secondNumber < 100 {
print("\(firstNumber) < \(secondNumber) < 100")
}
}
}
// Prints "4 < 42 < 100"
在if語句中使用可選綁定創(chuàng)建的常量和變量僅在if語句的主體中可用洽瞬。 相反,用guard語句創(chuàng)建的常量和變量在保護(hù)語句之后的代碼行中可用业汰。
隱式解包
- 如上所述伙窃,可選項指示允許常數(shù)或變量具有“nil”。 可選項可以使用if語句檢查以查看值是否存在样漆,并且可以使用可選綁定有條件地解開为障,以訪問可選值(如果存在)。
- 有時,從程序的結(jié)構(gòu)中可以清楚地看出产场,可選項將始終具有值鹅髓,在該值首次設(shè)置之后。 在這些情況下京景,刪除每次訪問可選值時都需要檢查和解開可選值窿冯,這是非常有用的,因為它可以安全地假定所有時間都有一個值确徙。
- 這些類型的可選項被定義為隱式解包的可選項醒串。 通過在要使其可選的類型之后放置感嘆號(String!)而不是問號(String鄙皇?)來編寫隱式解包的可選屬性芜赌。
- 當(dāng)Swift中隱式解包的可選屬性的主要用途是在類初始化期間。
隱式解包的可選是后臺的正嘲橐荩可選缠沈,但也可以像非可選值一樣使用,而不需要在每次訪問時解包可選值错蝴。 以下示例顯示了在將其包裝值作為顯式字符串訪問時洲愤,可選字符串和隱式未包裝可選字符串之間的行為差異:
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
您可以將隱式展開的可選項視為授予可選項在使用時自動展開的權(quán)限。 在每次使用可選名稱后顷锰,不要在可選名稱后面放置感嘆號柬赐,而是在聲明后在可選類型之后放置感嘆號。
注意:如果隱式解包的可選項為nil官紫,并且嘗試訪問其包裝值肛宋,則會觸發(fā)運(yùn)行時錯誤。 結(jié)果與在不包含值的正呈溃可選參數(shù)之后放置感嘆號完全相同酝陈。
您仍然可以將一個隱式解開的可選項(如普通可選項)視為是否包含值:
if assumedString != nil {
print(assumedString)
}
// Prints "An implicitly unwrapped optional string."
您還可以使用帶有可選綁定的隱式解包可選,以在單個語句中檢查和解包其值:
if let definiteString = assumedString {//如果隱式解包中的無值(nil)則視為解包失敗毁涉,如果有值沉帮,就把這個作為一個新值,去創(chuàng)建一個名為‘definiteString’的常量薪丁,這個常量在if的語句體內(nèi)可用。
print(definiteString)
}
// Prints "An implicitly unwrapped optional string."
注意:當(dāng)變量有可能在程序中變?yōu)閚il時馅精,不要使用隱式解包严嗜。 如果需要在變量的生命周期中檢查有沒有值,請始終使用正常的可選類型(在變量聲明的時候加洲敢?)漫玄。