
可選鏈接(自判斷鏈接)(Optional Chaining)是一種可以請(qǐng)求和調(diào)用屬性、方法及子腳本的過程,它的自判斷性體現(xiàn)于請(qǐng)求或調(diào)用的目標(biāo)當(dāng)前可能為空(nil)。如果自判斷的目標(biāo)有值,那么調(diào)用就會(huì)成功;相反,如果選擇的目標(biāo)為空(nil),則這種調(diào)用將返回空(nil)。多次請(qǐng)求或調(diào)用可以被鏈接在一起形成一個(gè)鏈,如果任何一個(gè)節(jié)點(diǎn)為空(nil)將導(dǎo)致整個(gè)鏈?zhǔn)А?/p>
簡單來說,就是被定義為可選類型的屬性,你在使用時(shí),不比強(qiáng)制解析,而是用可選鏈接,就是可選解析,因?yàn)?,可選類型可能為nil,如果你強(qiáng)制解析使用,則會(huì)發(fā)生運(yùn)行時(shí)錯(cuò)誤
注意: Swift的可選鏈接和Objective-C中的消息為空有些相像,但是Swift可以使用在任意類型中,并且失敗與否可以被檢測(cè)到。
可選鏈接可替代強(qiáng)制拆包
通過在想調(diào)用的屬性、方法、或子腳本的自判斷值(optional value)(非空)后面放一個(gè)問號(hào),可以定義一個(gè)自判斷鏈接。這一點(diǎn)很像在自判斷值后面放一個(gè)聲明符號(hào)來強(qiáng)制拆得其封包內(nèi)的值。他們的主要的區(qū)別在于當(dāng)自判斷值為空時(shí)可選鏈接即刻失敗,然而一般的強(qiáng)制拆包將會(huì)引發(fā)運(yùn)行時(shí)錯(cuò)誤。
為了反映可選鏈接可以調(diào)用空(nil),不論你調(diào)用的屬性、方法、子腳本等返回的值是不是自判斷值,它的返回結(jié)果都是一個(gè)自判斷值。你可以利用這個(gè)返回值來檢測(cè)你的自判斷鏈接是否調(diào)用成功,有返回值即成功,返回nil則失敗。
調(diào)用可選鏈接的返回結(jié)果與原本的返回結(jié)果具有相同的類型,但是原本的返回結(jié)果被包裝成了一個(gè)自判斷值,當(dāng)可選鏈接調(diào)用成功時(shí),一個(gè)應(yīng)該返回Int的屬性將會(huì)返回Int?。
下面幾段代碼將解釋可選鏈接和強(qiáng)制拆包的不同。
首先定義兩個(gè)類Person和Residence。
class Person {
var residence: Residence?
}
class Residence {
var numberOfRooms = 1
}
如果你創(chuàng)建一個(gè)新的Person實(shí)例,它的residence屬性由于是被定義為自判斷型的,此屬性將默認(rèn)初始化為空:
let john = Person()
如果你想使用聲明符!強(qiáng)制拆包獲得這個(gè)人residence屬性numberOfRooms屬性值,將會(huì)引發(fā)運(yùn)行時(shí)錯(cuò)誤,因?yàn)檫@時(shí)沒有可以供拆包的residence值。
//fatal error: unexpectedly found nil while unwrapping an Optional value
//拆包錯(cuò)誤,因?yàn)榭蛇x類型的值為nil
let roomCount = john.residence!.numberOfRooms
接下來我們使用可選鏈接,解析時(shí)把!改成?
//這告訴Swift來鏈接自判斷residence?屬性,如果residence存在則取回numberOfRooms的值。
let roomCount = john.residence?.numberOfRooms
print(roomCount ?? 5) //這種打印方法是當(dāng)roomCount為空時(shí),給一個(gè)默認(rèn)值5
因?yàn)檫@種嘗試獲得numberOfRooms的操作有可能失敗,自判斷鏈接會(huì)返回Int?類型值,或者稱作“可選Int”。當(dāng)residence是空的時(shí)候(上例),選擇Int將會(huì)為空,因此會(huì)出先無法訪問numberOfRooms的情況。
你可以自己定義一個(gè)Residence實(shí)例給john.residence,這樣它就不再為空了:
john.residence = Residence()
//john.residence 現(xiàn)在有了實(shí)際存在的實(shí)例而不是nil了。如果你想使用和前面一樣的自判斷鏈接來獲得numberOfRoooms,它將返回一個(gè)包含默認(rèn)值1的Int?:
if let roomCount = john.residence?.numberOfRooms {
print("John's residence has \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\(roomCount) room(s).")
} else {
print("Unable to retrieve the number of rooms.")
}
// 打印 "John's residence has 1 room(s)"。