Swift5.1—可选链式调用

简介: Swift5.1—可选链式调用

可选链式调用是一种可以在当前值可能为 nil 的可选值上请求和调用属性、方法及下标的方法。如果可选值有值,那么调用就会成功;如果可选值是 nil,那么调用将返回 nil。多个调用可以连接在一起形成一个调用链,如果其中任何一个节点为 nil,整个调用链都会失败,即返回 nil。


注意

Swift 的可选链式调用和 Objective-C 中向 nil 发送消息有些相像,但是 Swift 的可选链式调用可以应用于任意类型,并且能检查调用是否成功。


使用可选链式调用代替强制展开

通过在想调用的属性、方法,或下标的可选值后面放一个问号(?),可以定义一个可选链。这一点很像在可选值后面放一个叹号(!)来强制展开它的值。它们的主要区别在于当可选值为空时可选链式调用只会调用失败,然而强制展开将会触发运行时错误。

为了反映可选链式调用可以在空值(nil)上调用的事实,不论这个调用的属性、方法及下标返回的值是不是可选值,它的返回结果都是一个可选值。你可以利用这个返回值来判断你的可选链式调用是否调用成功,如果调用有返回值则说明调用成功,返回 nil 则说明调用失败。


这里需要特别指出,可选链式调用的返回结果与原本的返回结果具有相同的类型,但是被包装成了一个可选值。例如,使用可选链式调用访问属性,当可选链式调用成功时,如果属性原本的返回结果是 Int 类型,则会变为 Int? 类型。


下面几段代码将解释可选链式调用和强制展开的不同。


首先定义两个类PersonResidence

class Person {
    var residence: Residence?
}
class Residence {
    var numberOfRooms = 1
}


Residence有一个Int类型的属性numberOfRooms,其默认值为 1。Person具有一个可选的residence属性,其类型为 Residence?。


假如你创建了一个新的Person实例,它的residence属性由于是可选类型而将被初始化为nil,在下面的代码中john有一个值为nilresidence属性:

let john = Person()


如果使用叹号(!)强制展开获得这个johnresidence属性中的 numberOfRooms值,会触发运行时错误,因为这时residence没有可以展开的值:

let roomCount = john.residence!.numberOfRooms
// 这会引发运行时错误


john.residence为非nil值的时候,上面的调用会成功,并且把 roomCount设置为Int类型的房间数量。正如上面提到的,当 residencenil的时候,上面这段代码会触发运行时错误。


可选链式调用提供了另一种访问numberOfRooms的方式,使用问号(?)来替代原来的叹号(!):

if let roomCount = john.residence?.numberOfRooms {
    print("John's residence has \(roomCount) room(s).")
} else {
    print("Unable to retrieve the number of rooms.")
}
// 打印“Unable to retrieve the number of rooms.”


residence后面添加问号之后,Swift就会在residence不为nil的情况下访问numberOfRooms


因为访问numberOfRooms有可能失败,可选链式调用会返回Int? 类型,或称为“可选的 Int”。如上例所示,当residencenil的时候,可选的Int将会为nil,表明无法访问numberOfRooms。访问成功时,可选的Int值会通过可选绑定展开,并赋值给非可选类型的 roomCount常量。


要注意的是,即使numberOfRooms是非可选的Int时,这一点也成立。只要使用可选链式调用就意味着numberOfRooms会返回一个 Int?而不是Int

可以将一个Residence的实例赋给john.residence,这样它就不再是nil了:

john.residence = Residence()


john.residence现在包含一个实际的Residence实例,而不再是nil。如果你试图使用先前的可选链式调用访问numberOfRooms,它现在将返回值为 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).”


注:尝试对可选型进行解包 (用?),安全  optional chaining,

强制对可选型进行解包 (用!),确保不为空,否则报错,不安全。

目录
相关文章
|
2月前
|
Swift
Swift 可选链
Swift 可选链
14 0
|
2月前
|
存储 Swift iOS开发
Swift 闭包
10月更文挑战第28天
26 0
|
8月前
Swift4.0判断本函数是否在其它类有相同的方法
Swift4.0判断本函数是否在其它类有相同的方法
50 0
|
8月前
|
存储 Swift
Swift中,函数和闭包
Swift中,函数和闭包
80 1
|
存储 安全 Java
Swift5.0 - day5-继承、初始化、可选链、协议(上)
Swift5.0 - day5-继承、初始化、可选链、协议(上)
134 0
Swift5.0 - day5-继承、初始化、可选链、协议(上)
|
编译器 Swift C++
Swift5.0 - day2-流程控制、函数、枚举(上)
Swift5.0 - day2-流程控制、函数、枚举(上)
141 0
Swift5.0 - day2-流程控制、函数、枚举(上)
|
存储 编译器 Swift
Swift5.0 - day2-流程控制、函数、枚举(下)
Swift5.0 - day2-流程控制、函数、枚举(下)
85 0
Swift5.0 - day2-流程控制、函数、枚举(下)
|
存储 Swift
Swift5.0 - day5-继承、初始化、可选链、协议(下)
Swift5.0 - day5-继承、初始化、可选链、协议(下)
95 0
|
存储 Swift iOS开发
Swift5.1—闭包
Swift5.1—闭包
125 0
|
存储 Swift
Swift5.1—尾随闭包
Swift5.1—尾随闭包
277 0

热门文章

最新文章

相关课程

更多