可选链接(自判断链接)(Optional Chaining)是一种可以请求和调用属性、方法及子脚本的过程,它的自判断性体现于请求或调用的目标当前可能为空(nil)。如果自判断的目标有值,那么调用就会成功;相反,如果选择的目标为空(nil),则这种调用将返回空(nil)。多次请求或调用可以被链接在一起形成一个链,如果任何一个节点为空(nil)将导致整个链失效。
简单来说,就是被定义为可选类型的属性,你在使用时,不比强制解析,而是用可选链接,就是可选解析,因为,可选类型可能为nil,如果你强制解析使用,则会发生运行时错误
注意: Swift的可选链接和Objective-C中的消息为空有些相像,但是Swift可以使用在任意类型中,并且失败与否可以被检测到。
可选链接可替代强制拆包
通过在想调用的属性、方法、或子脚本的自判断值(optional value)(非空)后面放一个问号,可以定义一个自判断链接。这一点很像在自判断值后面放一个声明符号来强制拆得其封包内的值。他们的主要的区别在于当自判断值为空时可选链接即刻失败,然而一般的强制拆包将会引发运行时错误。
为了反映可选链接可以调用空(nil),不论你调用的属性、方法、子脚本等返回的值是不是自判断值,它的返回结果都是一个自判断值。你可以利用这个返回值来检测你的自判断链接是否调用成功,有返回值即成功,返回nil则失败。
调用可选链接的返回结果与原本的返回结果具有相同的类型,但是原本的返回结果被包装成了一个自判断值,当可选链接调用成功时,一个应该返回Int的属性将会返回Int?。
下面几段代码将解释可选链接和强制拆包的不同。
首先定义两个类Person和Residence。
class Person {
var residence: Residence?
}
class Residence {
var numberOfRooms = 1
}
如果你创建一个新的Person实例,它的residence属性由于是被定义为自判断型的,此属性将默认初始化为空:
let john = Person()
如果你想使用声明符!强制拆包获得这个人residence属性numberOfRooms属性值,将会引发运行时错误,因为这时没有可以供拆包的residence值。
//fatal error: unexpectedly found nil while unwrapping an Optional value
//拆包错误,因为可选类型的值为nil
let roomCount = john.residence!.numberOfRooms
接下来我们使用可选链接,解析时把!改成?
//这告诉Swift来链接自判断residence?属性,如果residence存在则取回numberOfRooms的值。
let roomCount = john.residence?.numberOfRooms
print(roomCount ?? 5) //这种打印方法是当roomCount为空时,给一个默认值5
因为这种尝试获得numberOfRooms的操作有可能失败,自判断链接会返回Int?类型值,或者称作“可选Int”。当residence是空的时候(上例),选择Int将会为空,因此会出先无法访问numberOfRooms的情况。
你可以自己定义一个Residence实例给john.residence,这样它就不再为空了:
john.residence = Residence()
//john.residence 现在有了实际存在的实例而不是nil了。如果你想使用和前面一样的自判断链接来获得numberOfRoooms,它将返回一个包含默认值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)"。