Swift可選鏈可替代強制解析
可選鏈可替代強制解析
通過在想調用的屬性、方法、或子腳本的可選值(optional value
)(非空)後面放一個問號,可以定義一個可選鏈。這一點很像在可選值後面放一個歎號來強制拆得其封包內的值。它們的主要的區別在於當可選值爲空時可選鏈即刻失敗,然而一般的強制解析將會引發運行時錯誤。
爲了反映可選鏈可以調用空(nil
),不論你調用的屬性、方法、子腳本等返回的值是不是可選值,它的返回結果都是一個可選值。你可以利用這個返回值來檢測你的可選鏈是否調用成功,有返回值即成功,返回nil則失敗。
調用可選鏈的返回結果與原本的返回結果具有相同的類型,但是原本的返回結果被包裝成了一個可選值,當可選鏈調用成功時,一個應該返回Int
的屬性將會返回Int?
。
下面幾段代碼將解釋可選鏈和強制解析的不同。
首先定義兩個類Person
和Residence
。
class Person {
var residence: Residence?
}
class Residence {
var numberOfRooms = 1
}
Residence
具有一個Int
類型的numberOfRooms
,其值爲 1。Person
具有一個可選residence
屬性,它的類型是Residence?
。
如果你創建一個新的Person
實例,它的residence
屬性由於是被定義爲可選型的,此屬性將默認初始化爲空:
let john = Person()
如果你想使用感嘆號(!
)強制解析獲得這個人residence
屬性numberOfRooms
屬性值,將會引發運行時錯誤,因爲這時沒有可以供解析的residence
值。
let roomCount = john.residence!.numberOfRooms
//將導致運行時錯誤
當john.residence
不是nil
時,會運行通過,且會將roomCount
設置爲一個int
類型的合理值。然而,如上所述,當residence
爲空時,這個代碼將會導致運行時錯誤。
可選鏈提供了一種另一種獲得numberOfRooms
的方法。利用可選鏈,使用問號來代替原來!
的位置:
if let roomCount = john.residence?.numberOfRooms {
println("John's residence has \(roomCount) room(s).")
} else {
println("Unable to retrieve the number of rooms.")
}
// 打印 "Unable to retrieve the number of rooms.
這告訴 Swift 來鏈接可選residence?
屬性,如果residence
存在則取回numberOfRooms
的值。
因爲這種嘗試獲得numberOfRooms
的操作有可能失敗,可選鏈會返回Int?
類型值,或者稱作「可選Int
」。當residence
是空的時候(上例),選擇Int
將會爲空,因此會出先無法訪問numberOfRooms
的情況。
要注意的是,即使numberOfRooms是非可選Int
(Int?
)時這一點也成立。只要是通過可選鏈的請求就意味着最後numberOfRooms
總是返回一個Int?
而不是Int
。
你可以自己定義一個Residence
實例給john.residence
,這樣它就不再爲空了:
john.residence = Residence()
john.residence
現在有了實際存在的實例而不是nil了。如果你想使用和前面一樣的可選鏈來獲得numberOfRoooms
,它將返回一個包含默認值 1 的Int?
:
if let roomCount = john.residence?.numberOfRooms {
println("John's residence has \(roomCount) room(s).")
} else {
println("Unable to retrieve the number of rooms.")
}
// 打印 "John's residence has 1 room(s)"。