选项链是使用选项来查询和调用其属性、方法或下标的一个过程,如果选项包含一个值,则属性、方法、下标的查询和调用成功,否则,调用返回nil。
选项链能用在任何类型的选项来检查对其一个属性、方法、下标的查询和调用是否成功。
选项链可以作为强制展开的替代方式使用,但选项链的使用更加安全,不会触发一个运行时错误。
在调用一个选项的属性、方法或下标方法时,通过在该选项值的后面放置一个(?)标记来规定一个选项链。这与在选项值后放置一个(!) 来强制展开选项的值非常相似。主要的不同是在选项值为nil时选项链能够得体的失败,不会触发一个运行时错误。
选项链与Objective-C语言中的发消息给nil类似,选项链能允许在一个nil值上进行属性、方法、下标的调用和查询。为了反应这个事实, 选项链的调用结果总是返回一个选项值,即使你查询的属性、方法、下标返回一个非选项值的情况。然后可以使用这个返回值来检查选项链的调用是否成功。
尤其是选项链的返回结果除了被封装为一个选项外与返回值的类型相同。如一个正常返回一个Int的属性当使用 选项链来存取时返回一个整形选项(Int?)。
下面例子展示了选项链的使用:
classPerson {
var residence:Residence?
}
class Residence {
var rooms =Room[]()
var numberOfRooms:Int {
return rooms.count
}
subscript(i:Int) ->Room {
return rooms[i]
}
var address:Address?
}
class Room {
let name:String
init(name:String) {self.name =name }
}
class Address {
var buildingName:String?
var buildingNumber:String?
var street:String?
func buildingIdentifier() ->String? {
if buildingName {
return buildingName
}else if buildingNumber {
return buildingNumber
}else {
return nil
}
}
}
let john =Person()
if let roomCount =john.residence?.numberOfRooms {
println("John's residence has(roomCount) room(s).")
}else {
println("Unable to retrieve the number of rooms.")
}
以上例子中john实例的属性residence是一个选项,在没有为john实例的属性residence赋值时,执行else分支,如果john实例的属性residence已经赋值,则执行if 分支。而无论哪种情况,代码都不会出现运行时错误。
多个选项链能链接到一起,如果链上的任何链接返回nil,则整个链失败。这允许检查和调用一个选项属性的子属性包含的属性、方法、下标方法以及更深的调用。如下例子展示了多个选项链如何链接到一起。
if let johnsStreet = john.residence?.address?.street {
println("John's street name is(johnsStreet).")
}else {
println("Unable to retrieve the address.")
}
下例展示如何通过选项链调用下标方法:
if let firstRoomName =john.residence?[0].name {
println("The first room name is(firstRoomName).")
}else {
println("Unable to retrieve the first room name.")
}
下例展示如何通过选项链调用一个实例方法。
if let buildingIdentifier =john.residence?.address?.buildingIdentifier() {
println("John's building identifier is(buildingIdentifier).")
}
由于Address实例方法buildingIdentifier返回的也是一个选项,因此还可以进一步链接。如下所示:
if let upper = john.residence?.address?.buildingIdentifier()?.uppercaseString {
println("John's uppercase building identifier is(upper).")
}