我们回顾一下可选类型,当你要使用可选类型的时候,首先必须要对其进行解包。但是存在一个问题就是,如果对一个为nil的可选类型进行强制解包的话,那么会产生运行时错误。第一种解决办法就是使用if语句先判断这个可选类型是否为nil,然后在访问其属性或方法。但是十分繁琐。考虑一下这个可选类型里面访问的属性还是可选类型的情况吧,多几层的时候,if的层数惨不忍睹。
一个很好的解决办法就是利用可选链(Optional Chaining)
语法很简单,把中间需要解包的可选类型的强制解包符号!替换成?
伪代码例子
if let 可选链返回值的解包 = 可选类型1?.可选类型2?.返回可选类型的方法1?.可选类型3 {
//<span style="font-family: Arial, Helvetica, sans-serif;">可选链返回值</span>不为nil
} else {
//<span style="font-family: Arial, Helvetica, sans-serif;">可选链返回值</span>为nil
}
解释:
首先检测可选类型1是否为nil,如果不会nil,那么解包。
然后检查可选类型1的属性——可选类型2是否为nil,不为nil,解包。
然后调用可选类型2的一个方法。这个方法会返回一个可选类型.成这个可选类型为可选类型A吧。
然后再对这个可选类型A进行判断,如果不为nil,解包。
最后利用if语句对可选类型A的属性——可选类型3进行判断处理。
注意点:
1、如果前面的每一次判断有一个为nil了。那么这个可选链直接返回nil,不会再对后面的可选链进行处理。
2、可选链返回的类型是可选链中最后一个类型对应的可选类型。假设上面伪代码中最后一个可选类型3改为一个非可选类型3(比如Int),那么这个链返回的是其对应的可选类型Int?
3、可选链最后不能再用?进行解包,必须用!。但是用!就会产生当可选类型为nil时报错的情况。所以为了判断是否为nil,只能用if。
上面的伪代码是访问可选类型的例子。对于给可选链赋值的例子的伪代码如下
可选类型1?.可选类型2?.返回可选类型的方法1?.类型3 = 赋值 //这句中的类型3可以是可选类型也可以是非可选类型。赋值成功与否都不会报错。
//借助if语句判断是否赋值成功
if (可选类型1?.可选类型2?.返回可选类型的方法1?.可选类型3 = 赋值 ) != nil { //<span style="color:#ff0000;">注意if中赋值语句的返回值是Void?</span>
//赋值成功
} else {
//赋值失败
}
class CPU {
var name: String?
func getClockSpeed() -> Double? {
if self.name != nil {
return 1.2
} else {
return nil
}
}
}
class Computer {
var cpu: CPU?
}
var c = Computer()
print(c.cpu?.name = "fef") //这句可选链的类型是Void?,打印 nil
print(c.cpu?.name) //这句可选链的类型是String?,打印 nil
c.cpu = CPU()
print(c.cpu?.getClockSpeed()?.isZero) //这句可选链的类型是Bool? ,打印 nil
print(c.cpu?.name = "Intel") //这句可选链的类型是Void?,打印 Optional(())
print(c.cpu?.name) //这句可选链类型是String?,打印 Optional("Intel")
print(c.cpu?.getClockSpeed()?.isZero) //这句可选链的类型是Bool? ,打印 Optional(false)